2016-04-11 18 views
6

Ricevo un oggetto dinamico di tipo "Sealed Class" da un driver api (in dll). Voglio decorare questo oggetto con alcune proprietà aggiuntive.è possibile convertire un oggetto dinamico in un ExpandoObject (C#)

Vorrei fare qualcosa per l'effetto di:

public void expandIT(dynamic sealedObject) { 

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

UPDATE

Mi piace la soluzione di JCL. Ma per quello che volevo fare, era più facile creare un oggetto ExpandoObject e quindi incorporare l'oggetto classe sealed Dynamic come proprietà child, e quindi aggiungere le mie proprietà al padre ExpandoObject. Grazie JCL, ero nel congelatore del cervello su come farlo. I

risposta

10

No. Un oggetto dynamic non applica il tipo al momento della compilazione, ma non rende magicamente espandibile il tuo oggetto (a meno che non sia un ExpandoObject).

È possibile tuttavia, fare una sorta di involucro o proxy utilizzando DynamicObject ... qualcosa come:

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

e quindi è possibile utilizzarlo come:

dynamic myExpandedObject = new ExpandedObjectFromApi(sealedObject); 

Ciò dovrebbe restituire l'originale proprietà dell'oggetto se trovato, o se nessuna proprietà di quel nome è nell'oggetto originale, la aggiungerà come proprietà "personalizzata".

Ho creato il codice nell'editor Stack Overflow e probabilmente ho commesso un sacco di errori, non è adatto per copia/incolla, e ha bisogno di un sacco di controllo degli errori (deve anche implementare campi e metodi, se il ricevuto oggetto li ha). L'ho appena scritto in modo da ottenere l'idea di base.

Si potrebbe anche voler aggiungere una proprietà speciale (ad esempio, WrappedObject, ad esempio) e acquisirla in TryGetMember, in modo da poter recuperare l'oggetto originale.

+0

Se si implementa qualcosa di simile e si ha bisogno di prestazioni, proprio come un suggerimento, creo un qualche tipo di cache per 'PropertyInfo' restituito da' GetPropertyInfo'. La riflessione è sempre un po 'lenta :-) – Jcl

Problemi correlati