C # Buddy Classes / Метаданные и отражения - PullRequest
5 голосов
/ 02 марта 2010

Я пытаюсь использовать рефлексию, чтобы проверить, имеют ли свойства в данном классе установленный атрибут ReadOnly. Я использую классы MVC View Models (для метаданных используется частичный «приятельский» класс.

 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. Если я установлю атрибут ReadOnly в свойстве Balance AccountViewModel, я смогу получить его следующим образом:

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

Я не могу получить информацию об атрибуте, если он находится в классе метаданных. Как я могу проверить, существует ли атрибут? У меня есть классы метаданных, определенные для всех моих моделей представлений, и мне нужен общий способ проверки атрибутов в классах метаданных.

Есть предложения?

Ответы [ 2 ]

7 голосов
/ 02 марта 2010

решение состоит в том, чтобы использовать GetCustomAttributes для получения типов метаданных и проверки их свойств ...

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 голос
/ 02 марта 2010

Ниже приведен короткий, но рабочий пример, обратите внимание, что я создал вложенный класс 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...