4

Hier meine Entwicklung Voraussetzung ist,Abrufen von Modellnamen in benutzerdefinierten Anzeigenamen Attribut

My Label-Werte werden in der Datenbank gespeichert sind, und ich möchte noch die Daten Anmerkung in einer deklarativen Weise verwenden, ist dies mein Modell zu machen lesbarer.

Und hier ist mein Ansatz,

entschied ich mich individuellen Displaynamen zu schreiben, wo der Standardwert von meinem Modell zur Verfügung gestellt wird durch den aus der Datenbank abgerufen Wert überschreibt.

Hier wird die Eigenschaft im Modell definiert ist,

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

Hier wird der Name Attributklasse benutzerdefinierte Anzeige ist,

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

Nun Sie im obigen Code sehen können, ist Modelname etwas, das ich brauche, aber ich habe nicht !!

Beim Debuggen, ich grabe in ModelMetadataProviders.Current und kann die Verfügbarkeit des aktuellen Modells in Aktion sehen. Da es sich jedoch um nicht öffentliche statische Mitglieder handelt, kann ich nicht über meinen Code darauf zugreifen.

enter image description here

ich die unten Methode geschrieben haben, den Modellnamen durch Reflektion abzurufen,

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

Aber das Problem ist, stellt die Typen Sammlung mir Einträge für alle Modelle (mindestens einmal besucht vom Benutzer). Und es gibt keinen Hinweis darauf, was gerade in Aktion ist !!

enter image description here

Antwort

0

IMHO Attribute sollten nicht verwendet werden, um Datenbank-Anrufe zu tätigen. Attribute sollten zum Hinzufügen von Metadaten zu Klassen/Eigenschaften usw. verwendet werden.

Wenn Sie also Ihren Code so ändern möchten, dass er eher der Microsoft-Architektur für MVC entspricht, verfügen Sie über Ihr benutzerdefiniertes Attribut und einen benutzerdefinierten ModelMetadataProvider :

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

    public string Name { get; private set; } 
} 

Dann wird ein neuer 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; 
    } 
} 

Wo

public class MyViewModel 
{ 
    public MyPropertyType PropertyName { get; set; } 
} 
  • container = MyViewModel
  • modeltype = MyPropertyType
  • property = Property

dann den Provider (global.asax oder was auch immer) registrieren:

ModelMetadataProviders.Current = new LocalizedModelMetadataProvider(); 

Sie können auch einen Blick an der ModelMetadata hat es ein paar andere Dinge, die Sie vielleicht in der Zukunft ändern möchten.

Verwandte Themen