开发者

C# Buddy Classes / Meta Data and Reflection

I am trying to use reflection to check if properties on a given class have a ReadOnly attribu开发者_运维百科te set. The classes I am using are MVC View Models (using a partial "buddy" class for the metadata.

 public partial class AccountViewModel  
{
    public virtual Int32 ID { get; set; } 
    public virtual decimal Balance { get; set; }    

} 
[MetadataType(typeof(AccountViewModelMetaData))]
public partial class AccountViewModel  
{
    class AccountViewModelMetaData
    {
        [DisplayName("ID")]
        public virtual Int32 ID { get; set; }

        [DisplayName("Balance")]
        [DataType(DataType.Currency)] 
        [ReadOnly(true)]
        public virtual decimal Balance { get; set; }

    }
}

I want to check if "Balance" has the ReadOnly property. If i set the ReadOnly attribute on the Balance property of AccountViewModel, i can retrieve it this way:

Type t = typeof(AccountViewModel);
PropertyInfo pi = t.GetProperty("Balance");  
bool isReadOnly =  ReadOnlyAttribute.IsDefined(pi,typeof( ReadOnlyAttribute);

I can't retrieve the attribute info if it is on the meta data class. How can i check if the attribute exists? I have meta data classes defined for all my view models, and need a generic way to check for attributes on meta data classes.

Any suggestions?


the solution is to use GetCustomAttributes to get MetaData types and check the properties on those as well...

Type t = typeof(MyClass);
PropertyInfo pi = t.GetProperty(PropertyName);  
bool isReadOnly = ReadOnlyAttribute.IsDefined(pi, typeof(ReadOnlyAttribute));

if (!isReadOnly)
{
    //check for meta data class.
    MetadataTypeAttribute[] metaAttr = (MetadataTypeAttribute[])t.GetCustomAttributes(typeof(MetadataTypeAttribute),true);

    if (metaAttr.Length > 0)
    {
        foreach (MetadataTypeAttribute attr in metaAttr)
        {
            t = attr.MetadataClassType;
            pi = t.GetProperty(PropertyName);

            if (pi != null) isReadOnly = ReadOnlyAttribute.IsDefined(pi, typeof(ReadOnlyAttribute));

            if (isReadOnly) break;
        }
    }
} 


A short but working example follows, note that I made the nested class internal in order to be visible to the outside.

public partial class AccountViewModel
{
    internal class AccountViewModelMetaData
    {
        public virtual Int32 ID { get; set; }
        [ReadOnlyAttribute(false)]
        public virtual decimal Balance { get; set; }
    }

    public virtual Int32 ID { get; set; }
    public virtual decimal Balance { get; set; }
}
class Program
{
    public static void Main(string[] args)
    {
        Type metaClass = typeof(AccountViewModel.AccountViewModelMetaData);

        bool hasReadOnlyAtt = HasReadOnlyAttribute(metaClass, "Balance");

        Console.WriteLine(hasReadOnlyAtt);
    }

    private static bool HasReadOnlyAttribute(Type type, string property)
    {
        PropertyInfo pi = type.GetProperty(property);

        return ReadOnlyAttribute.IsDefined(pi, typeof(ReadOnlyAttribute));
    }
}

Also be aware that this checks for the existence of the attribute. You can has in this example specify the attribute but provide the value of false. If you want to check if the property is read-only or not, you can't only use the method ReadOnlyAttribute.IsDefined.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜