attribute.isdefined는 메타 다타 타입 클래스에 적용되는 속성이 보이지 않습니다
-
19-09-2019 - |
문제
내가 부분 클래스에 속성을 적용하면 메타 다타 타입 속성, 이러한 속성은 찾을 수 없습니다 attribute.isdefined (). 누구든지 왜 내가 뭘 잘못하고 있는지 아는 사람이 있습니까?
아래는 내가 이것을 위해 만든 테스트 프로젝트이지만 실제로 LINQ에서 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<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 개의 장소 (메인 클래스 및 메타 데이터 클래스)를 찾는 추상화를 숨기는 것입니다.
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;
}
일반적인 사용을위한 내 솔루션. 당신이 찾고있는 속성 속성을 얻으십시오. 찾을 수없는 경우 NULL을 반환하십시오.
발견되면 속성 자체를 반환합니다. 따라서 WIH가있는 경우 속성 내의 속성에 액세스 할 수 있습니다.
이 도움을 희망합니다.
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;
}
다음 수업이 주어지면 :
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 답변을 사용하여 이와 같은 코드를 수정하여 다음과 같습니다.
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.");
}
제휴하지 않습니다 StackOverflow