4

Вот мое требование развития,Получить название модели в пользовательский атрибут Отображаемое имя

Мои значений меток хранятся в базе данных, и я все еще хочу использовать аннотацию данных декларативно, это сделать мою модель более читаемым.

А вот мой подход,

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

Здесь свойство определяется в модели,

[CustomDisplay(Name: "First Name")] 
    [CustomRequired(ErrorMessage: "{0} is required")] 
    public String FirstName { get; set; } 

Вот ПОЛЬЗ.ДИСПЛЕЙ класс имя атрибута,

public class CustomDisplayAttribute : DisplayNameAttribute 
{ 
    private string _defaultName; 
    private string _displayName; 

    public CustomDisplayAttribute(string Name) 
    { 
     _defaultName = Name; 
    } 

    public override string DisplayName 
    { 
     get 
     { 
      if (String.IsNullOrEmpty(_displayName)) 
      { 
       _displayName = DAO.RetrieveValue(**ModelName**, _defaultName); 
      } 
      return _displayName; 
     } 
    } 
} 

Теперь вы можете увидеть в приведенном выше коде, ModelName то, что я нужно, но у меня нет !!

В процессе отладки я копаюсь в ModelMetadataProviders.Current и может видеть доступность текущей модели в действии. Но, поскольку он является частью непубличных статических членов, я не могу получить доступ к нему через свой код.

enter image description here

Я написал метод ниже, чтобы получить имя модели с помощью отражения,

private static string GetModelName() 
{ 
    var modelName = String.Empty; 
    FieldInfo info = typeof(CachedAssociatedMetadataProvider<CachedDataAnnotationsModelMetadata>) 
         .GetField("_typeIds", BindingFlags.NonPublic | BindingFlags.Static); 
    var types = (ConcurrentDictionary<Type, string>)info.GetValue(null); 
    modelName = types.FirstOrDefault().Key.Name; 
    return modelName; 
} 

Но проблема в том, коллекция типов предоставляет мне записи для всех моделей (посещенных по крайней мере один раз пользователем). И нет никакой подсказки, чтобы знать, которая в настоящее время находится в действии!

enter image description here

ответ

0

ИМХО Атрибуты должны не быть использованы для обращения к базе данных. Атрибуты следует использовать для добавления метаданных в классы/свойства и т. Д.

Итак, если вы захотите изменить свой код, чтобы быть похожим на архитектуру Microsoft для MVC, тогда у вас будет свой собственный атрибут и пользовательский ModelMetadataProvider :

public class CustomDisplayAttribute : Attribute 
{ 
    public CustomDisplayAttribute(string name) 
    { 
     Name = name; 
    } 

    public string Name { get; private set; } 
} 

Тогда новый ModelMetadataProvider:

public class DatabaseModelMetadataProvider : DataAnnotationsModelMetadataProvider 
{ 
    public DatabaseModelMetadataProvider() 
    { 
    } 

    protected override ModelMetadata CreateMetadata(
    IEnumerable<Attribute> attributes, 
    Type containerType, 
    Func<object> modelAccessor, 
    Type modelType, 
    string propertyName) 
    { 
    var metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName); 

    var displayAttribute = containerType == null 
     ? null as CustomDisplayAttribute 
     : containerType.GetProperty(propertyName) 
      .GetCustomAttributes(false) 
      .OfType<CustomDisplayAttribute>() 
      .FirstOrDefault(); 
    if (displayAttribute != null) 
    { 
     var displayValue = DAO.RetrieveValue(containerType.ToString(), displayAttribute.Name) 

     metadata.DisplayName = displayValue; 
    } 
    return metadata; 
    } 
} 

Где

public class MyViewModel 
{ 
    public MyPropertyType PropertyName { get; set; } 
} 
  • containerType = MyViewModel
  • modelType = MyPropertyType
  • ИмениСвойства = PropertyName

Затем зарегистрировать поставщика (global.asax или любой другой):

ModelMetadataProviders.Current = new LocalizedModelMetadataProvider(); 

Также вы можете взглянуть на ModelMetadata у него есть несколько других вещей, которые вы, возможно, захотите изменить в будущем.