开发者

Error while reflecting through custom attributes

开发者 https://www.devze.com 2023-03-24 01:10 出处:网络
I am trying to fetch the values of certain fields of a class based on their names and the presence of a customized attribute through reflection.

I am trying to fetch the values of certain fields of a class based on their names and the presence of a customized attribute through reflection. My Custom attribute is :

 [AttributeUsage (AttributeTargets.All, AllowMultiple=true)]
public sealed class ColumnAttribute : Attribute
{
    internal string name = "";
    internal string length = "";
    internal string precision = "";

    public ColumnAttribute() { }
    public ColumnAttribute(String name) { this.name = name; }
    public ColumnAttribute(String name, String length) { }
    public ColumnAttribute(String name, String length, String precision) { }

    public String Name { get { return name; } set { name = value; } }
    public String Length { get { return length; } set { length = value; } }
    public String Precision { get { return precision; } set { precision = value; } }
}

A sample class that uses this is :

class SampleEntity
{
    //private int number;
    public string name;
    //float marks;

    public virtual int Number { get; set; }
    public SampleEntity() { }
    public SampleEntity(int number)
    {
        this.Number = number;
    }
    public void conversation(string request, string response) { }

    public void ordinary() {
        Console.Write("This isn't ordinary...");
    }
    [ColumnAttribute (Name = "XWBCCD")]
    public String XWBCCD { get; set; }

    [ColumnAttribute (Name = "XWBNCD")]
    public String XWBNCD { get; set; }

I am also having a different class that's having different field names :

 class SampleRepository
{

    [ColumnAttribute(Name = "XWBCCD")]
    public String SomeOtherFieldName { get; set; }

    [ColumnAttribute(Name = "XWBNCD")]
    public String XWBNCD { get; set; }

    [ColumnAttribute(Name = "XWBWCD")]
    public String XWBWCD { get; set; }
}

Through reflection, I am trying to copy values by matching the attribute 'name' parameter rather than the fieldname. Trouble is, that during reflection, such comparison is not happening through getCustomAttributes() method passed over fields. My approach to solve this problem (That's failing so far ) has been : First I pass on 2 objects, objSrc (of first class, which is populated) and objDesc (of second class that's empty)

 FieldInfo[] srcFields = objSrc.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.IgnoreCase |Bi开发者_开发知识库ndingFlags.FlattenHierarchy);
        FieldInfo[] destFields = objDest.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty);

Then I am trying to iteratively perform reflection over all fields

foreach (FieldInfo srcFld in srcFields)
        {
            foreach (FieldInfo destFld in destFields)
            {
                if (((MemberInfo)srcFld).Name.Equals(((MemberInfo)destFld).Name)){
                    destFld.SetValue(objDest, srcFld.GetValue(objSrc));
                    break;
                }
                object[] srcAttr = srcFld.GetCustomAttributes(true);
                object[] destAttr = destFld.GetCustomAttributes(true);

                if (Utils.Length(srcAttr) == 1 && Utils.Length(destAttr) == 1){

                    if ((srcAttr[0]).Equals(destAttr[0]) && srcFld.FieldType.Equals(destFld.FieldType))
                        destFld.SetValue(objDest, srcFld.GetValue(objSrc));
                    else
                        break;
                }

            }
        }

Trouble happens on the GetCustomAttributes() method as it is returning null.


I apologize for the vb.net code instead of c#, but I happen to have had a linqpad file where I was doing exactly the same thing, here ya go:

(Not really production ready code at all, but it gets the idea across I hope.)

Sub Main

    dim data as DataRow = GetSomeData.GetData(2311385).rows(0)

    dim dm as IDataMapper = new DataMapper()

    dim login as LoginData = dm.MapDataTo(of LoginData)(data)

    data.Dump()
    login.dump()

End Sub

public interface IDataMapper
    function MapDataTo(of T as {IDataMappable,new})(data as DataRow) as T
end interface

public interface IDataMappable
end interface

public class DataMapper
    implements IDataMapper
    Public Function MapDataTo(Of T As {New, IDataMappable})(ByVal data As System.Data.DataRow) As T Implements IDataMapper.MapDataTo
        dim mapToObj as new T
        dim properties() as PropertyInfo = gettype(T).GetProperties()
        for each propInfo as PropertyInfo in properties
            Dim attributes() As Attribute = propInfo.GetCustomAttributes(GetType(DataMappingAttribute), True)
            if attributes.length > 0 then
                Dim dataAttribute As DataMappingAttribute = CType(attributes(0), DataMappingAttribute)
                Dim column As String = dataAttribute.ColumnName
                Dim dataType As Type = dataAttribute.DataType
                propInfo.SetValue(mapToObj, Convert.ChangeType(data(column), dataType), Nothing)
            end if
        next
        return mapToObj
    end function
end class

<AttributeUsage(AttributeTargets.Property)> _
public class DataMappingAttribute
    inherits Attribute
    private _ColumnName as string
    Public readonly Property ColumnName() As String
        Get
            return _ColumnName
        End Get
    End Property
    private _DataType as Type
    Public readonly Property DataType() As Type
        Get
            return _DataType
        End Get
    End Property
    public sub new(ColumnName as string, DataType as Type)
        me._columnName = ColumnName
        me._DataType = DataType
    end sub 
end class


public class LoginData
    implements IDataMappable

    private _LoginID as integer
    <DataMappingAttribute("loginID",Gettype(integer))> _
    public property LoginID as integer
        get
            return _LoginID
        end get
        set(value as integer)
            _LoginID = value
        end set
    end property

    private _LoginName as string
    <DataMappingAttribute("loginName",Gettype(String))> _
    public property LoginName as string
        get
            return _LoginName
        end get
        set(value as string)
            _LoginName = value
        end set
    end property

    private _FirstName as string
    <DataMappingAttribute("firstName",Gettype(String))> _
    public property FirstName as string
        get
            return _FirstName
        end get
        set(value as string)
            _FirstName = value
        end set
    end property

    private _LastName as string
    <DataMappingAttribute("lastName",Gettype(String))> _
    public property LastName as string
        get
            return _LastName
        end get
        set(value as string)
            _LastName = value
        end set
    end property

    private _EmailAddress as string
    <DataMappingAttribute("emailAddress",Gettype(String))> _
    public property EmailAddress as string
        get
            return _EmailAddress
        end get
        set(value as string)
            _EmailAddress = value
        end set
    end property

end class

public class GetSomeData
    Public shared Function GetData(ByVal ID As Integer) As DataTable
            'return a datatable
    End Function
end class
0

精彩评论

暂无评论...
验证码 换一张
取 消