views:

379

answers:

1

If I apply attributes to a partial class via the MetadataType attribute, those attributes are not found via Attribute.IsDefined(). Anyone know why, or what I'm doing wrong?

Below is a test project I created for this, but I'm really trying to apply custom attributes to a LINQ to SQL entity class - like this answer in this question.

Thanks!

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
    {
    }
}
+1  A: 

The MetadataType attribute is used to specify help specify the additional information on the data object. To access the additional attributes you would need to do something like the following:

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

This also includes a sample attribute to show how to extract info that was added.

Adam Gritt
Awesome - thanks Adam. Here's another helpful page:http://www.jarrettmeyer.com/2009/07/using-data-annotations-with-metadata.htmlOne thing I'm still wondering is which libraries can you use MetadataType with? To find attributes defined in a MetadataType class you really have to be looking for them, and it seems like not all standard .NET libraries would do that. Apparently MetadataType is used with ASP.NET - are there other standard places? Anyway, thanks again.
shaunmartin
I am not sure if there are standard places or not. Most of the description for the class itself centers around usage with the new Data object support (ie Entity Framework, LINQ to SQL, etc). This would make the most sense as it allows the addition of additional validation attributes.
Adam Gritt