문제

내가 부분 클래스에 속성을 적용하면 메타 다타 타입 속성, 이러한 속성은 찾을 수 없습니다 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.");
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top