2016-04-11 10 views
6

Otrzymuję dynamiczny obiekt typu "Sealed Class" z api sterownika (w dll). Chcę ozdobić ten obiekt kilkoma dodatkowymi właściwościami.można przekonwertować obiekt dynamiczny na obiekt ExpandoObject (C#)

Chciałbym zrobić coś do skutku:

public void expandIT(dynamic sealedObject) { 

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

UPDATE

Lubię rozwiązanie JCL za. Ale do tego, co chciałem zrobić, łatwiej było utworzyć obiekt ExpandoObject, a następnie osadzić obiekt klasy Dynamic zaplombowany jako własność potomną, a następnie dodać moje właściwości do obiektu nadrzędnego ExpandoObject. Dzięki JCL byłem w zamrożeniu mózgu, jak to zrobić. I

Odpowiedz

10

Nie. Obiekt dynamic nie wymusza typu w czasie kompilacji, ale nie powoduje magicznej rozbudowy obiektu (chyba że jest to ExpandoObject).

Można jednak dokonać pewnego rodzaju opakowaniu jednostkowym lub pełnomocnika użyciu DynamicObject ... coś jak:

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

a następnie można go używać jak:

dynamic myExpandedObject = new ExpandedObjectFromApi(sealedObject); 

Należy zwrócić oryginał właściwości obiektu, jeśli znaleziono, lub jeśli nie ma właściwości o tej nazwie w oryginalnym obiekcie, doda go jako "niestandardową" właściwość.

Zrobiłem kod w edytorze stosu przepełnienia i prawdopodobnie popełniłem wiele błędów, nie nadaje się do kopiowania/wklejania i wymaga tonu sprawdzania błędów (również wymaga zastosowania pól i metod, jeśli odebrane obiekt je ma). Po prostu napisałem to, więc masz podstawowy pomysł.

Możesz również dodać specjalną właściwość (np. O nazwie WrappedObject) i przechwycić ją w TryGetMember, aby odzyskać oryginalny obiekt.

+0

Jeśli zaimplementujesz coś takiego i potrzebujesz wydajności, tak jak sugestia, zrobię coś w rodzaju pamięci podręcznej dla 'PropertyInfo' zwróconego przez' GetPropertyInfo'. Odbicie jest zawsze nieco powolne :-) – Jcl

Powiązane problemy