Attribute.IsDefined没有看到使用MetadataType类应用的属性

如果我通过MetadataType属性将属性应用于部分类,则不会通过Attribute.IsDefined()找到这些属性。 任何人都知道为什么,或者我做错了什么?

下面是我为此创建的测试项目,但我真的尝试将自定义属性应用于LINQ to SQL实体类 – 就像这个问题中的答案一样。

谢谢!

using System; using System.ComponentModel.DataAnnotations; using System.Reflection; namespace MetaDataTest { class Program { static void Main(string[] args) { PropertyInfo[] properties = typeof(MyTestClass).GetProperties(); foreach (PropertyInfo propertyInfo in properties) { Console.WriteLine(Attribute.IsDefined(propertyInfo, typeof(MyAttribute))); Console.WriteLine(propertyInfo.IsDefined(typeof(MyAttribute), true)); Console.WriteLine(propertyInfo.GetCustomAttributes(true).Length); // Displays: // False // False // 0 } Console.ReadLine(); } } [MetadataType(typeof(MyMeta))] public partial class MyTestClass { public string MyField { get; set; } } public class MyMeta { [MyAttribute()] public string MyField { get; set; } } [AttributeUsage(AttributeTargets.All)] public class MyAttribute : System.Attribute { } } 

MetadataType属性用于指定帮助指定有关数据对象的附加信息。 要访问其他属性,您需要执行以下操作:

 using System; using System.Linq; using System.ComponentModel.DataAnnotations; using System.Reflection; namespace MetaDataTest { class Program { static void Main(string[] args) { MetadataTypeAttribute[] metadataTypes = typeof(MyTestClass).GetCustomAttributes(typeof(MetadataTypeAttribute), true).OfType().ToArray(); MetadataTypeAttribute metadata = metadataTypes.FirstOrDefault(); if (metadata != null) { PropertyInfo[] properties = metadata.MetadataClassType.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { Console.WriteLine(Attribute.IsDefined(propertyInfo, typeof(MyAttribute))); Console.WriteLine(propertyInfo.IsDefined(typeof(MyAttribute), true)); Console.WriteLine(propertyInfo.GetCustomAttributes(true).Length); RequiredAttribute attrib = (RequiredAttribute)propertyInfo.GetCustomAttributes(typeof(RequiredAttribute), true)[0]; Console.WriteLine(attrib.ErrorMessage); } // Results: // True // True // 2 // MyField is Required } Console.ReadLine(); } } [MetadataType(typeof(MyMeta))] public partial class MyTestClass { public string MyField { get; set; } } public class MyMeta { [MyAttribute()] [Required(ErrorMessage="MyField is Required")] public string MyField { get; set; } } [AttributeUsage(AttributeTargets.All)] public class MyAttribute : System.Attribute { } } 

这还包括一个示例属性,用于显示如何提取已添加的信息。

我有类似的情况。 我最后为它编写了以下扩展方法。 我们的想法是隐藏2个地方(主要类和元数据类)的抽象概念。

  static public Tattr GetSingleAttribute(this PropertyInfo pi, bool Inherit = true) where Tattr : Attribute { var attrs = pi.GetCustomAttributes(typeof(Tattr), Inherit); if (attrs.Length > 0) return (Tattr)attrs[0]; var mt = pi.DeclaringType.GetSingleAttribute(); if (mt != null) { var pi2 = mt.MetadataClassType.GetProperty(pi.Name); if (pi2 != null) return pi2.GetSingleAttribute(Inherit); } return null; } 

我的通用解决方案。 获取您要查找的属性的属性。 如果未找到则返回null。

如果找到,则返回属性本身。 因此,如果您愿意,您可以访问属性中的属性。

希望这有帮助。

 public static Attribute GetAttribute(this PropertyInfo PI, T t) where T: Type { var Attrs = PI.DeclaringType.GetCustomAttributes(typeof(MetadataTypeAttribute), true); if (Attrs.Length < 1) return null; var metaAttr = Attrs[0] as MetadataTypeAttribute; var metaProp = metaAttr.MetadataClassType.GetProperty(PI.Name); if (metaProp == null) return null; Attrs = metaProp.GetCustomAttributes(t, true); if (Attrs.Length < 1) return null; return Attrs[0] as Attribute; } 

鉴于以下类别:

 public partial class Person { public int PersonId { get; set; } } [MetadataType(typeof(PersonMetadata))] public partial class Person { public partial class PersonMetadata { [Key] public int PersonId { get; set; } } } 

我需要查看是否已在Person类的属性上定义了Key 。 然后我需要获得该物业的价值。 使用@AdamGrid回答,我修改了这样的代码来获取它:

 private static object GetPrimaryKeyValue(TEntity entity) { MetadataTypeAttribute[] metadataTypes = typeof(TEntity).GetCustomAttributes(typeof(MetadataTypeAttribute), true).OfType().ToArray(); MetadataTypeAttribute metadata = metadataTypes.FirstOrDefault(); if (metadata == null) { ThrowNotFound(); } PropertyInfo[] properties = metadata.MetadataClassType.GetProperties(); PropertyInfo primaryKeyProperty = properties.SingleOrDefault(x => Attribute.GetCustomAttribute(x, typeof(KeyAttribute)) as KeyAttribute != null); if (primaryKeyProperty == null) { ThrowNotFound(); } object primaryKeyValue = typeof(TEntity).GetProperties().Single(x => x.Name == primaryKeyProperty.Name).GetValue(entity); return primaryKeyValue; } private static void ThrowNotFound() { throw new InvalidOperationException ($"The type {typeof(TEntity)} does not have a property with attribute KeyAttribute to indicate the primary key. You must add that attribute to one property of the class."); }