2016-04-11 16 views
6

Ich bekomme ein dynamisches Objekt vom Typ "Sealed Class" von einem Treiber API (in DLL). Ich möchte dieses Objekt mit ein paar zusätzlichen Eigenschaften dekorieren.kann man ein dynamisches Objekt in ein ExpandoObject konvertieren (C#)

Ich möchte etwas auf die Wirkung tun:

public void expandIT(dynamic sealedObject) { 

    ExpandoObject expand = new ExpandoObject(sealedObject); 
    expand.time = DateTime.Now(); 
    etc.... 
} 

UPDATE

Ich mag Lösung des JCL. Aber für das, was ich tun wollte, war es einfacher, ein ExpandoObject zu erstellen und dann das dynamische Sealed-Klassenobjekt als Kind-Eigenschaft einzubetten und dann meine Eigenschaften dem übergeordneten ExpandoObject hinzuzufügen. Danke, JCL, ich war im Begriff zu verstehen, wie das geht. I

Antwort

10

Nein. Ein dynamic Objekt erzwingt den Typ zum Zeitpunkt der Kompilierung nicht, aber es macht Ihr Objekt nicht magisch erweiterbar (es sei denn, es handelt sich um eine ExpandoObject).

Sie kann jedoch eine Art Wrapper oder Proxy machen DynamicObject mit ... so etwas wie:

public class ExpandedObjectFromApi : DynamicObject 
{ 
    private Dictionary<string, object> _customProperties = new Dictionary<string, object>(); 
    private object _currentObject; 

    public ExpandedObjectFromApi(dynamic sealedObject) 
    { 
     _currentObject = sealedObject; 
    } 

    private PropertyInfo GetPropertyInfo(string propertyName) 
    { 
     return _currentObject.GetType().GetProperty(propertyName); 
    } 

    public override bool TryGetMember(GetMemberBinder binder, out object result) 
    { 
     var prop = GetPropertyInfo(binder.Name); 
     if(prop != null) 
     { 
     result = prop.GetValue(_currentObject); 
     return true; 
     } 
     result = _customProperties[binder.Name]; 
     return true;   
    }  

    public override bool TrySetMember(SetMemberBinder binder, object value) 
    { 
     var prop = GetPropertyInfo(binder.Name); 
     if(prop != null) 
     { 
     prop.SetValue(_currentObject, value); 
     return true; 
     } 
     if(_customProperties.ContainsKey(binder.Name)) 
     _customProperties[binder.Name] = value; 
     else 
     _customProperties.Add(binder.Name, value); 
     return true;   
    }  
} 

Und dann können Sie es mögen verwenden:

dynamic myExpandedObject = new ExpandedObjectFromApi(sealedObject); 

Dies sollte die Original zurückkehren Wenn Objekteigenschaften gefunden werden oder wenn keine Eigenschaft dieses Namens im ursprünglichen Objekt vorhanden ist, wird sie als "benutzerdefinierte" Eigenschaft hinzugefügt.

Ich habe den Code im Stack Overflow-Editor gemacht und wahrscheinlich viele Fehler gemacht, es ist nicht zum Kopieren/Einfügen geeignet, und es braucht Tonnen Fehlerprüfung (muss auch Felder und Methoden implementieren, wenn die empfangen Objekt hat sie). Einfach geschrieben, damit Sie die Grundidee bekommen.

Sie können auch eine spezielle Eigenschaft (z. B. WrappedObject) hinzufügen und in TryGetMember erfassen, damit Sie das ursprüngliche Objekt zurückbekommen.

+0

Wenn Sie so etwas implementieren und Leistung benötigen, nur als Vorschlag, würde ich eine Art Cache für die von 'GetPropertyInfo' zurückgegebene' PropertyInfo' erstellen. Die Reflexion ist immer ein bisschen langsam :-) – Jcl

Verwandte Themen