2016-08-24 3 views
0

Ich mache eine Attributklasse, die ein generisches nimmt. Diese generische Klasse wäre eine Klasse, die der Benutzer erstellt, die den Abschnitt appSettings in der Konfigurationsdatei nachahmt. Sie erstellen für jeden Schlüssel eine Eigenschaft, und mit diesem Attribut können sie diesen Schlüssel diesem Feld zuordnen. Wenn sie meine Klasse instanziieren, indem ich ihre Klasse als generische Klasse verwende, durchsuche ich ihre Klasse nach meinem Attribut und wenn ich gefunden habe, benutze ich den Namen, den sie gesetzt haben, um diesen appSetting-Schlüssel zu finden und dann diesen Eigenschaftswert auf diesen appSetting-Wert zu setzen Geben Sie ihre Eigenschaften ein.In C# ändern Sie eine Eigenschaft in schreibgeschützt zur Laufzeit

Also im Grunde ist dies ein Mapping-Attribut, das die appSettings in der Konfigurationsdatei stark eingibt. Es macht es so, dass das Mapping in einer Klasse erfolgt, anstatt dass der Benutzer es inline in seinem Code tun muss und es aufstaut. Schönes und sauberes Mapping.

Mein letzter Schritt ist, dass ich ihre Eigenschaften als schreibgeschützt markieren will, aber ich kann nicht herausfinden, wie das zu tun, wie die CanWrite Eigenschaft der Propertyinfo-Klasse selbst schreibgeschützt ist.

/// <summary> 
    /// This class will fill in the fields of the type passed in from the config file because it's looking for annotations on the type 
    /// </summary> 
    public class StrongConfiguration<T> where T: class 
    { 
     // this is read only 
     public T AppSettings { get; private set; } 

     public StrongConfiguration() 
     { 
      AppSettings = (T)Activator.CreateInstance(typeof(T)); 

      // find properties in this type that have the ConfigAttribute attribute on them 
      var props = from p in AppSettings.GetType().GetProperties() 
         let attr = p.GetCustomAttributes(typeof(ConfigAttribute), true) 
         where attr.Length == 1 
         select new { Property = p, Attribute = attr.First() as ConfigAttribute }; 

      // find the config setting from the ConfigAttribute value on each property and set it's value casting to the propeties type 
      foreach (var p in props) 
      { 
       var appSettingName = ConfigurationManager.AppSettings[p.Attribute.ConfigName]; 

       var value = Convert.ChangeType(appSettingName, p.Property.PropertyType); 

       p.Property.SetValue(AppSettings, value); 

       // todo: I want to set this propety now as read-only so they can't change it but not sure how 
      } 
     } 
    } 
+0

Hier wollen Sie wahrscheinlich 'Emit' verwenden und es proxy-out. Sie können Metadaten zur Laufzeit nicht ändern ... – code4life

+0

Noch nie gehört von Emit, aber es scheint wie eine ganz neue Welt. Ich werde tiefer graben. – user441521

+1

Irgendein Grund für die Abstimmung unten? Was habe ich falsch gemacht? Es ist nett, für zukünftige Referenz zu wissen. – user441521

Antwort

2

Zwei Dinge, ist ein C# nicht generische Attributklassen ermöglichen. Das wird also nicht funktionieren.

Zweitens, Sie können die Eigenschaft nicht ändern, um nur zur Laufzeit zu lesen. Reflection dient zum Überprüfen der Metadaten der geladenen Typen, ohne die Metadaten zu ändern.

Sie könnten die Eigenschaften selbst sichern, aber das ist ein größeres Unterfangen.

+0

Entschuldigung, ich hätte klarer sein sollen, das ist nicht die Attributklasse, es ist die eigentliche "Bibliotheks" -Klasse, stark appSettings in app.config zu bekommen. Die Attributklasse ist getrennt davon, aber dies macht die ganze Arbeit des Lesens der Konfigurationsdatei und des Bestimmens, welche Eigenschaft in dem generischen Typ erhalten werden soll, den der Benutzer basierend auf den Eigenschaften, die mit meinem Attribut versehen sind, erhalten. Eine Art Bummer, den Sie zur Laufzeit nicht auf Nur-Lesen umstellen können. Was meinst du zurück die Eigenschaften selbst? Es gibt auch ReadOnly-Attribute in der Component-Klasse. Ändert das nicht, dass diese Eigenschaft nur gelesen werden soll? – user441521

+1

Um eine Eigenschaft als nur zur Laufzeit lesend zu markieren, kann die Codegenerierung 'Reflection.Emit' oder' Mono.Cecil' verwendet werden. Aber ich sehe keine Probleme mit privaten Set Accessor von Eigentum. Warum brauchst du genau Readonly Modifikator? Willst du vermeiden, dass jemand durch Reflektion eine Eigenschaft setzt? Aber ich denke, es ist in Ordnung, wenn jemand es versucht, so ist es in der Tat erforderlich für ihn – Serg046

+0

@ Serg046 Ich denke, in der Regel dachte ich seit app.config ist (zum größten Teil) gemeint, nur gelesen zu werden, dass diese Eigenschaften auch sein sollten schreibgeschützt. Es ist nicht das Ende der Zeiten, wenn sie es nicht sind, sondern nur versucht haben, mehr Standard im Sinne der app.config-Idee zu sein. – user441521

Verwandte Themen