代码之家  ›  专栏  ›  技术社区  ›  shaunmartin

attribute.isDefined未看到用metadatatype类应用的属性

  •  21
  • shaunmartin  · 技术社区  · 15 年前

    如果我通过 MetadataType attribute ,未通过以下方式找到这些属性: Attribute.IsDefined() . 有人知道为什么,或者我做错了什么吗?

    下面是我为此创建的一个测试项目,但我确实在尝试将自定义属性应用于Linq to SQL实体类,比如 this answer in this question .

    谢谢!

    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
        {
        }
    }
    
    4 回复  |  直到 7 年前
        1
  •  22
  •   Adam Gritt    15 年前

    这个 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<MetadataTypeAttribute>().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
  •  3
  •   Rajesh Kumar    14 年前

    我也有类似的情况。最后我为它编写了以下扩展方法。 其思想是隐藏在两个位置(主类和元数据类)中查找的抽象。

        static public Tattr GetSingleAttribute<Tattr>(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<MetadataTypeAttribute>();
            if (mt != null)
            {
                var pi2 = mt.MetadataClassType.GetProperty(pi.Name);
                if (pi2 != null)
                    return pi2.GetSingleAttribute<Tattr>(Inherit);
            }
            return null;
        }
    
        3
  •  0
  •   s k    9 年前

    我的通用解决方案。获取您要查找的属性。如果找不到,则返回空值。

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

    希望这有帮助。

    public static Attribute GetAttribute<T>(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;
    }
    
        4
  •  0
  •   CodingYoshi    7 年前

    考虑到以下类别:

    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; }
        }
    }
    

    我需要看看 Key 已在的属性上定义 Person 班级。然后我需要得到财产的价值。使用@adamgrid answer,我修改了如下代码以获得它:

    private static object GetPrimaryKeyValue(TEntity entity)
    {
        MetadataTypeAttribute[] metadataTypes = typeof(TEntity).GetCustomAttributes(typeof(MetadataTypeAttribute), true).OfType<MetadataTypeAttribute>().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.");
    }