C# Attribute.IsDefined不';看不到应用于MetadataType类的属性

C# Attribute.IsDefined不';看不到应用于MetadataType类的属性,c#,linq-to-sql,attributes,metadata,custom-attributes,C#,Linq To Sql,Attributes,Metadata,Custom Attributes,如果我通过将属性应用于某个分部类,则无法通过找到这些属性。有人知道为什么,或者我做错了什么吗 下面是我为此创建的一个测试项目,但我确实在尝试将自定义属性应用于LINQtoSQL实体类 谢谢 using System; using System.ComponentModel.DataAnnotations; using System.Reflection; namespace MetaDataTest { class Program { static void M

如果我通过将属性应用于某个分部类,则无法通过找到这些属性。有人知道为什么,或者我做错了什么吗

下面是我为此创建的一个测试项目,但我确实在尝试将自定义属性应用于LINQtoSQL实体类

谢谢

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<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
    {
    }
}
使用系统;
使用System.Linq;
使用System.ComponentModel.DataAnnotations;
运用系统反思;
命名空间元数据测试
{
班级计划
{
静态void Main(字符串[]参数)
{
MetadataTypeAttribute[]metadataTypes=typeof(MyTestClass).GetCustomAttributes(typeof(MetadataTypeAttribute),true).OfType().ToArray();
MetadataTypeAttribute元数据=metadataTypes.FirstOrDefault();
if(元数据!=null)
{
PropertyInfo[]properties=metadata.MetadataClassType.GetProperties();
foreach(PropertyInfo属性中的PropertyInfo)
{
WriteLine(Attribute.IsDefined(propertyInfo,typeof(MyAttribute));
WriteLine(propertyInfo.IsDefined(typeof(MyAttribute),true));
WriteLine(propertyInfo.GetCustomAttributes(true.Length));
RequiredAttribute attrib=(RequiredAttribute)propertyInfo.GetCustomAttributes(typeof(RequiredAttribute),true)[0];
Console.WriteLine(属性错误消息);
}
//结果:
//真的
//真的
// 2
//MyField是必需的
}
Console.ReadLine();
}
}
[元数据类型(typeof(MyMeta))]
公共部分类MyTestClass
{
公共字符串MyField{get;set;}
}
公共类MyMeta
{
[MyAttribute()]
[必需(ErrorMessage=“MyField是必需的”)]
公共字符串MyField{get;set;}
}
[属性设置(AttributeTargets.All)]
公共类MyAttribute:System.Attribute
{
}
}

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

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

static public Tattr GetSingleAttribute(此属性info pi,bool Inherit=true),其中Tattr:Attribute
{
var attrs=pi.GetCustomAttributes(typeof(Tattr),Inherit);
如果(属性长度>0)
返回(Tattr)属性[0];
var mt=pi.DeclaringType.GetSingleAttribute();
如果(mt!=null)
{
var pi2=mt.MetadataClassType.GetProperty(pi.Name);
如果(pi2!=null)
返回pi2.GetSingleAttribute(继承);
}
返回null;
}

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

如果找到,它将返回属性本身。因此,您可以访问属性中的属性(如果您选择)

希望这能有所帮助

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;
}
公共静态属性GetAttribute(此属性info PI,T),其中T:Type
{
var Attrs=PI.DeclaringType.GetCustomAttributes(typeof(MetadataTypeAttribute),true);
if(Attrs.Length<1)返回null;
var metaAttr=Attrs[0]作为MetadataTypeAttribute;
var metaProp=metaAttr.MetadataClassType.GetProperty(PI.Name);
if(metaProp==null)返回null;
Attrs=metaProp.GetCustomAttributes(t,true);
if(Attrs.Length<1)返回null;
返回属性Attrs[0];
}

给定以下类别:

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 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.");
}
私有静态对象GetPrimaryKeyValue(TEntity实体)
{
MetadataTypeAttribute[]metadataTypes=typeof(tenty).GetCustomAttributes(typeof(MetadataTypeAttribute),true).OfType().ToArray();
MetadataTypeAttribute元数据=metadataTypes.FirstOrDefault();
if(元数据==null)
{
ThrowNotFound();
}
PropertyInfo[]properties=metadata.MetadataClassType.GetProperties();
PropertyInfo primaryKeyProperty=
properties.SingleOrDefault(x=>Attribute.GetCustomAttribute(x,typeof(KeyAttribute))作为KeyAttribute!=null);
如果(primaryKeyProperty==null)
{
ThrowNotFound();
}
对象primaryKeyValue=typeof(tenty).GetProperties().Single(x=>x.Name==primaryKeyProperty.Name).GetValue(实体);
返回primaryKeyValue;
}
私有静态void ThrowNotFound()
{
抛出新的InvalidOperationException
($“类型{typeof(TEntity)}没有具有属性KeyAttribute的属性来指示主键。必须将该属性添加到类的一个属性。”);
}

太棒了-谢谢亚当。这是另一个有用的页面:我仍然想知道的是,哪些库可以使用MetadataType?要查找MetadataType类中定义的属性,您必须查找它们,而且似乎并非所有标准的.NET库都会这样做。显然,MetadataType与ASP.NET一起使用-还有其他标准位置吗?无论如何,再次感谢。我不确定是否有标准的地方。对类本身的大部分描述都围绕着使用新的数据对象支持(即实体框架、LINQ到SQL等)来进行。这将是最有意义的,因为它允许添加额外的验证属性
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.");
}