C#好友类/元数据和反思

时间:2010-03-02 16:10:07

标签: c# .net reflection attributes

我正在尝试使用反射来检查给定类上的属性是否设置了ReadOnly属性。我使用的类是MVC视图模型(使用元数据的部分“伙伴”类。

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

    }
}

我想检查“Balance”是否具有ReadOnly属性。如果我在AccountViewModel的Balance属性上设置ReadOnly属性,我可以这样检索它:

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

如果它位于元数据类中,我无法检索属性信息。如何检查属性是否存在?我为所有视图模型定义了元数据类,并且需要通用的方法来检查元数据类的属性。

有什么建议吗?

2 个答案:

答案 0 :(得分:7)

解决方案是使用GetCustomAttributes来获取MetaData类型并检查这些类型的属性...

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

答案 1 :(得分:1)

下面是一个简短但有效的例子,请注意我创建了嵌套类internal,以便对外部可见。

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

还要注意,这会检查属性是否存在。您可以在此示例中指定属性,但提供false的值。如果要检查属性是否为只读,则不仅可以使用ReadOnlyAttribute.IsDefined方法。