Custom Attributes on Class Members

最后都变了- 提交于 2019-11-30 07:14:26

You can't really do this, unless you're using C# 3.0 in which case you'll need to rely on LINQ (ehm, expression trees).

What you do is that you create a dummy method for a lambda expression which lets the compiler generate the expression tree (compiler does the type checking). Then you dig into that tree to get the member. Like so:

static FieldInfo GetField<TType, TMemberType>(
    Expression<Func<TType, TMemberType>> accessor)
{
    var member = accessor.Body as MemberExpression;
    if (member != null)
    {
        return member.Member as FieldInfo;
    }
    return null; // or throw exception...
}

Given the following class:

class MyClass
{
    public int a;
}

You can get the meta data like this:

// get FieldInfo of member 'a' in class 'MyClass'
var f = GetField((MyClass c) => c.a); 

With a reference to that field you can then dig up any attribute the usual way. i.e. reflection.

static TAttribute GetAttribute<TAttribute>( 
    this MemberInfo member ) where TAttribute: Attribute
{
    return member.GetCustomAttributes( typeof( TAttribute ), false )
        .Cast<TAttribute>().FirstOrDefault<TAttribute>();
}

Now you can dig up an attribute on any field by something which is in large checked by the compiler. It also works with refactoring, if you rename 'a' Visual Studio will catch that.

var attr = GetField((MyClass c) => c.a).GetAttribute<DisplayNameAttribute>();
Console.WriteLine(attr.DisplayName);

There's not a single literal string in that code there.

You can do half of it a bit more simply:

    foreach (PropertyMapping attrib in
        Attribute.GetCustomAttributes(i, typeof(PropertyMapping)))
    {
        ret += map.FieldName; // whatever you want this to do...
    }

btw; you should make a habit of ending attributes with the word Attribute. Even if this causes duplication (see [XmlAttributeAttribute]).

However - re serialization; that isn't always trivial. A deceptive amount of code goes into serialization frameworks like Json.NET etc. The normal approach might be to get a type-converter, but in many ways this is easier with a PropertyDescriptor:

    foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(obj))
    {
        Console.WriteLine("{0}={1}",
            prop.Name, prop.Converter.ConvertToInvariantString(
                prop.GetValue(obj)));
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!