Классы дружбы С#/метаданные и отражение
Я пытаюсь использовать отражение, чтобы проверить, имеют ли свойства в данном классе атрибут ReadOnly. Классы, которые я использую, - это модели MVC View (с использованием частичного "приятеля" для метаданных.
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; }
}
}
Я хочу проверить, имеет ли свойство "Баланс" свойство ReadOnly. Если я устанавливаю атрибут ReadOnly в свойстве Balance AccountViewModel, я могу получить его следующим образом:
Type t = typeof(AccountViewModel);
PropertyInfo pi = t.GetProperty("Balance");
bool isReadOnly = ReadOnlyAttribute.IsDefined(pi,typeof( ReadOnlyAttribute);
Я не могу получить информацию об атрибуте, если она находится в классе метаданных. Как проверить, существует ли атрибут? У меня есть классы метаданных, определенные для всех моделей моего представления, и вам нужен общий способ проверки атрибутов в классах метаданных.
Любые предложения?
Ответы
Ответ 1
решение заключается в использовании 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;
}
}
}
Ответ 2
Ниже приведен короткий, но рабочий пример, обратите внимание, что я сделал вложенный класс 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
.