2015-10-05 12 views
9

Si consideri il seguente codicecast oggetto dinamico immettere dati utilizzando riflessione C#

var currentType = Type.GetType("Some.Type, Some"); 
dynamic myDynamic = new System.Dynamic.ExpandoObject(); 
myDynamic.A = "A"; 
var objectInCorrectType = ??? 

Come ho lanciato la dinamica al currentType?

+5

Non è possibile. O fai un cast di reinterpretazione, che in pratica dice "So che questo riferimento è in realtà una X masquerading come Y, quindi gettalo su X per me, reinterpretando il riferimento come riferimento a X", o fai una conversione che coinvolge codice che fa la conversione, come creare una nuova X e copiare i valori, ecc. Non esiste un modo integrato per convertire o trasmettere da ExpandoObject a un tipo specifico, è necessario crearlo tu stesso. –

risposta

9

Non è possibile trasmettere un oggetto dinamico a un tipo specifico, come commentato da @Lasse.

Tuttavia, la tua domanda menzioni "riflesso", così ho il sospetto che stai cercando un modo per mappare semplicemente i valori delle proprietà (vale a dire "la creazione di un nuovo X e la copia sui valori, ecc" in commento di Lasse):

... 
myDynamic.A = "A"; 

// get settable public properties of the type 
var props = currentType.GetProperties(BindingFlags.Public | BindingFlags.Instance) 
    .Where(x => x.GetSetMethod() != null); 

// create an instance of the type 
var obj = Activator.CreateInstance(currentType); 

// set property values using reflection 
var values = (IDictionary<string,object>)myDynamic; 
foreach(var prop in props) 
    prop.SetValue(obj, values[prop.Name]); 
+1

Questo era quello che cercavo, grazie :) –

+0

@TimGeyssens Se questa è la tua risposta, contrassegnala come risposta ... –

+0

@verarind done :) –

3

dynamic è duck-typing una variabile (ad esempio ritardare il controllo del tipo in fase di esecuzione). Conserva ancora un oggetto digitato ma non viene controllato durante la compilazione.

Pertanto, poiché un ExpandoObject è un tipo sia se lo si assegna a un riferimento digitato o dinamico, non è possibile eseguire il cast o convertire un ExpandoObject in un tipo solo perché condivide gli stessi membri del tipo di destinazione.

BTW, dal momento che ExpandoObject attrezzi IDictionary<string, object>, è possibile implementare una sorta di mappatura on-the-fly dall'istanza ExpandoObject al tipo di destinazione in cui un membro corrisponde come un metodo di estensione:

public static class ExpandObjectExtensions 
{ 
    public static TObject ToObject<TObject>(this IDictionary<string, object> someSource, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public) 
      where TObject : class, new() 
    { 
     Contract.Requires(someSource != null); 
     TObject targetObject = new TObject(); 
     Type targetObjectType = typeof (TObject); 

     // Go through all bound target object type properties... 
     foreach (PropertyInfo property in 
        targetObjectType.GetProperties(bindingFlags)) 
     { 
      // ...and check that both the target type property name and its type matches 
      // its counterpart in the ExpandoObject 
      if (someSource.ContainsKey(property.Name) 
       && property.PropertyType == someSource[property.Name].GetType()) 
      { 
       property.SetValue(targetObject, someSource[property.Name]); 
      } 
     } 

     return targetObject; 
    } 
} 

Ora, provate la codice seguente e ti funzionare come previsto:

public class A 
{ 
    public int Val1 { get; set; } 
} 

// Somewhere in your app... 
dynamic expando = new ExpandoObject(); 
expando.Val1 = 11; 

// Now you got a new instance of A where its Val1 has been set to 11! 
A instanceOfA = ((ExpandoObject)expando).ToObject<A>(); 

in realtà, ho basato questo risposta su un altro Q & a dove ho potuto risolvere un problema simile di carta ping oggetti al dizionario e viceversa: Mapping object to dictionary and vice versa.

Problemi correlati