2009-12-15 11 views
21

ile uygulanan özellikleri görmezse MetadataType attribute aracılığıyla kısmi sınıfa öznitelikleri uygularsam, bu öznitelikleri Attribute.IsDefined() aracılığıyla bulamaz. Herkes neden olduğunu ya da yanlış yaptığımı biliyor mu?Attribute.IsDefined, MetadataType sınıfı

Aşağıda, bunun için oluşturduğum bir test projesi var, ancak gerçekten bir özelliğe LINQ için SQL varlık sınıfına - this answer in this question gibi - uygulamak istiyorum.

Teşekkürler!

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 
    { 
    } 
} 
+0

onay bu şuna, ben zaten burada http://stackoverflow.com/a/24757520/3050647 – elia07

+0

onay bunun bu soruya: @AdamGrid cevabı kullanarak, böyle kod almak için modifiye Bu soruya şu soruyu zaten cevaplandırdım: http://stackoverflow.com/a/24757520/3050647 – elia07

cevap

22

MetadataType nitelik veri nesne üzerinde ek bilgileri belirtmek yardımcı belirtmek için kullanılır. ek özellikleri erişmek için aşağıdaki gibi bir şey yapmak gerekir:

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

Bu aynı zamanda eklenmiştir bilgi ayıklamak için nasıl göstermek için bir örnek niteliği içermektedir.

+1

Harika - teşekkürler Adam. İşte bir başka yararlı sayfa: http://www.jarrettmeyer.com/2009/07/using-data-annotations-with-metadata.html MetadataType ile hangi kütüphaneleri kullanabileceğinizi merak ediyorum. MetadataType sınıfında tanımlanan öznitelikleri bulmak için onları gerçekten aramak zorundasınız ve standart .NET kitaplıkları bunu yapmaz gibi görünüyor. Görünüşte MetadataType ASP.NET ile birlikte kullanılıyor - başka standart yerler var mı? Neyse, tekrar teşekkürler. – shaunmartin

+0

Standart yerler olup olmadığından emin değilim. Sınıfın açıklamasının çoğu, yeni Veri nesnesi desteğiyle (yani Entity Framework, LINQ to SQL, vb.) Kullanım alanı etrafında merkezlenir. Bu, ek doğrulama özelliklerinin eklenmesine izin verdiği ölçüde en mantıklı olacaktır. –

3

Benzer bir durum vardı. Bunun için aşağıdaki uzantı yöntemini yazdım. Fikir, 2 yere (ana sınıf ve meta veri sınıfı) bakma özetini gizlemektir.

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

Bunu kullandım, ancak PropertyInfo'yu genişletmek için MemberInfo'yı genişletmek için kullanıldı - pi.DeclaringType.GetSingleAttribute satırı, üye bilgisi olmayan bir anahtar olmadan derlenmedi. –

0

Genel kullanım için çözümüm. Niteliği, aradığınız özelliği alın. Bulunamadıysa null değerini döndür.

Bulunursa, özniteliğin kendisini döndürür. Böylece, özniteliğin içindeki özelliklere erişebilirsin.

Bu yardımı umut eder.

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

Verilen aşağıdaki sınıfları:

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

Ben KeyPerson sınıfı için bir mülk üzerinde tanımlı olup olmadığını görmek almak gerekiyordu. Daha sonra mülkün değerini almak için gerekli.

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."); 
}