未应用 C# 自定义属性

C# Custom Attributes not being applied

我正在尝试使用 MetadataType 属性 class 将属性应用于字段。我无法将自定义属性应用于部分 class 中的字段。我一直关注的一些示例是 here and here.

我的最终目标是尝试标记 class 中我需要 "do some work with" 的所有字段。

在下面的示例中,我希望字段 "Name" 应用 FooAttribute。在现实生活中,我正在处理生成的代码....

在我非常人为的例子中,我有一个部分 class - Cow,它是生成的代码;

namespace Models
{
    public partial class Cow
    {
        public string Name;
        public string Colour;
    }
}

我需要 Name 字段来使用我的 FooAttribute,所以我这样做了;

using System;
using System.ComponentModel.DataAnnotations;

namespace Models
{
    public class FooAttribute : Attribute { }

    public class CowMetaData
    {
        [Foo]
        public string Name;
    }

    [MetadataType(typeof(CowMetaData))]
    public partial class Cow
    {
        [Foo]
        public int Weight;

        public string NoAttributeHere;
    }

}

这对应用了 FooAttribute 的权重字段非常有效 - 但我希望如此,因为它在部分 class 中。 Name 字段没有从元数据中获取属性,而这正是我真正需要的。

我错过了什么,还是我完全错了?

更新: 这就是我使用 FooAttribute 搜索字段的方式;

public static void ShowAllFieldsWithFooAttribute(Cow cow)
{
    var myFields = cow.GetType().GetFields().ToList();
    foreach (var f in myFields)
    {
        if (Attribute.IsDefined(f, typeof(FooAttribute)))
        {
            Console.WriteLine("{0}", f.Name);
        }
    }
}

结果是:
体重

但我很期待:
姓名
体重

属性是元数据的一部分,不会影响编译结果。将 MetadataType 属性设置为 class 不会将所有元数据传播到 class 的 properties/fields。因此,您必须阅读代码中的 MetadataType 属性,并使用 MetadataType 属性中定义的类型的元数据而不是初始 class (或在您的情况下一起使用)

检查样本:

    var fooFields = new Dictionary<FieldInfo, FooAttribute>();

    var cowType = typeof (Cow);
    var metadataType = cowType.GetCustomAttribute<MetadataTypeAttribute>();
    var metaFields = metadataType?.MetadataClassType.GetFields() ?? new FieldInfo[0];

    foreach (var fieldInfo in cowType.GetFields())
    {
        var metaField = metaFields.FirstOrDefault(f => f.Name == fieldInfo.Name);
        var foo = metaField?.GetCustomAttribute<FooAttribute>() 
                           ?? fieldInfo.GetCustomAttribute<FooAttribute>();
        if (foo != null)
        {
            fooFields[fieldInfo] = foo;
        }
    }