C# Attribute.IsDefined不';看不到应用于MetadataType类的属性
如果我通过将属性应用于某个分部类,则无法通过找到这些属性。有人知道为什么,或者我做错了什么吗 下面是我为此创建的一个测试项目,但我确实在尝试将自定义属性应用于LINQtoSQL实体类 谢谢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
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.");
}