2013-04-04 25 views
54

Ich weiß, dass es einige Fragen, die diese Adresse, aber die Antworten in der Regel folgen entlang der Linien eines Wörterbuchs oder Sammlung von Parametern zu empfehlen, die nicht in meiner Situation nicht funktioniert.Dynamisch C# Eigenschaften zur Laufzeit

ich eine Bibliothek verwende, die durch Reflexion arbeitet viele kluge Dinge mit Objekten mit Eigenschaften zu tun. Dies funktioniert sowohl mit definierten Klassen als auch mit dynamischen Klassen. Ich brauche noch einen Schritt weiter zu gehen und tut etwas in diese Richtung:

public static object GetDynamicObject(Dictionary<string,object> properties) { 
    var myObject = new object(); 
    foreach (var property in properties) { 
     //This next line obviously doesn't work... 
     myObject.AddProperty(property.Key,property.Value); 
    } 
    return myObject; 
} 

public void Main() { 
    var properties = new Dictionary<string,object>(); 
    properties.Add("Property1",aCustomClassInstance); 
    properties.Add("Property2","TestString2"); 

    var myObject = GetDynamicObject(properties); 

    //Then use them like this (or rather the plug in uses them through reflection) 
    var customClass = myObject.Property1; 
    var myString = myObject.Property2; 

} 

Die Bibliothek funktioniert gut mit einem dynamischen Variablentyp, mit Eigenschaften manuell zugewiesen. Ich weiß jedoch nicht, wie viele oder welche Eigenschaften vorher hinzugefügt werden.

Antwort

75

Haben Sie einen Blick auf ExpandoObject genommen?

sehen: http://blogs.msdn.com/b/csharpfaq/archive/2009/10/01/dynamic-in-c-4-0-introducing-the-expandoobject.aspx

Von MSDN:

Die ExpandoObject Klasse ermöglicht es Ihnen, Mitglieder ihrer Instanzen zur Laufzeit und auch zu setzen und erhalten Werte dieser Elemente hinzuzufügen und zu löschen. Diese Klasse unterstützt die dynamische Bindung, die Sie Standardsyntax wie sampleObject.sampleMember statt komplexe Syntax wie sampleObject.GetAttribute („sampleMember“) zu verwenden, ermöglicht.

Erlauben Sie coole Dinge wie zu tun:

dynamic dynObject = new ExpandoObject(); 
dynObject.SomeDynamicProperty = "Hello!"; 
dynObject.SomeDynamicAction = (msg) => 
    { 
     Console.WriteLine(msg); 
    }; 

dynObject.SomeDynamicAction(dynObject.SomeDynamicProperty); 

Basierend auf Ihren aktuellen Code können Sie in mehr interessieren:

public static dynamic GetDynamicObject(Dictionary<string, object> properties) 
{ 
    return new MyDynObject(properties); 
} 

public sealed class MyDynObject : DynamicObject 
{ 
    private readonly Dictionary<string, object> _properties; 

    public MyDynObject(Dictionary<string, object> properties) 
    { 
     _properties = properties; 
    } 

    public override IEnumerable<string> GetDynamicMemberNames() 
    { 
     return _properties.Keys; 
    } 

    public override bool TryGetMember(GetMemberBinder binder, out object result) 
    { 
     if (_properties.ContainsKey(binder.Name)) 
     { 
      result = _properties[binder.Name]; 
      return true; 
     } 
     else 
     { 
      result = null; 
      return false; 
     } 
    } 

    public override bool TrySetMember(SetMemberBinder binder, object value) 
    { 
     if (_properties.ContainsKey(binder.Name)) 
     { 
      _properties[binder.Name] = value; 
      return true; 
     } 
     else 
     { 
      return false; 
     } 
    } 
} 

Auf diese Weise brauchen Sie nur:

var dyn = GetDynamicObject(new Dictionary<string, object>() 
    { 
     {"prop1", 12}, 
    }); 

Console.WriteLine(dyn.prop1); 
dyn.prop1 = 150; 

Ableiten von DynamicObject ermöglicht es Ihnen, Ihre eigene Strategie für die Behandlung dieser dynamischen Mitgliederanträge zu entwickeln, Vorsicht, es gibt Monster hier: der Compiler wird nicht in der Lage sein, viele Ihrer dynamischen Anrufe zu überprüfen, und Sie werden nicht Holen Sie sich Intellisense, denken Sie daran.

17

Dank @Clint für die große Antwort:

Ich wollte nur zeigen, wie einfach es ist dies mit der Expando Objekt zu lösen war:

public static dynamic GetDynamicObject(Dictionary<string,object> properties) { 
    var dynamicObject = new ExpandoObject() as IDictionary<string, Object>; 
    foreach (var property in properties) { 
     dynamicObject.Add(property.Key,property.Value); 
    } 
    return dynamicObject; 
} 
+6

+1. Anmerkung: Warum geben Sie kein Dictionary statt dynamic zurück? (zumindest IDictionary)? Ich meine, die Rückkehr der Dynamik ist ein wenig "irreführend", da Sie immer ein Wörterbuch zurückgeben werden. – Veverke

Verwandte Themen