2012-05-22 12 views
6

Attualmente sto usando Generics per realizzare alcuni metodi dinamici, come la creazione di un oggetto e il riempimento delle proprietà con i valori.Creazione di variabili generiche da un tipo - Come? O utilizzare Activator.CreateInstance() con proprietà {} anziché parametri()?

C'è un modo per creare "dinamicamente" il Generico senza conoscere il tipo? Per esempio:

List<String> = new List<String>() 

è un modo predefinied, ma

List<(object.GetType())> = new List<(object.GetType()>() 

non funziona ... Ma si può?

questo non sta funzionando (Esiste un approccio simile che funziona?)

public T CreateObject<T>(Hashtable values) 
    { 
     // If it has parameterless constructor (I check this beforehand) 
     T obj = (T)Activator.CreateInstance(typeof(T)); 

     foreach (System.Reflection.PropertyInfo p in typeof(T).GetProperties()) 
     { 
      // Specifically this doesn't work 
      var propertyValue = (p.PropertyType)values[p.Name]; 
      // Should work if T2 is generic 
      // var propertyValue = (T2)values[p.Name]; 

      obj.GetType().GetProperty(p.Name).SetValue(obj, propertyValue, null); 
     } 
    } 

Così, in breve: Come prendere un "Tipo" e creare un oggetto da che senza usare Generics? Ho usato solo metodi generici finora, ma è possibile utilizzare allo stesso modo le variabili? Devo definire un Generico (T) prima del metodo, quindi posso fare lo stesso sulle variabili prima di "crearle"?

... o come utilizzare "Attivatore" per creare un oggetto con Proprietà invece di Parametri. Come si fa qui:

// Con Parametri Valori

Test t = new Test("Argument1", Argument2); 

// Con le proprietà

Test t = new Test { Argument1 = "Hello", Argument2 = 123 }; 

risposta

13

È possibile utilizzare MakeGenericType:

Type openListType = typeof(List<>); 
Type genericListType = openListType.MakeGenericType(obj.GetType()); 
object instance = Activator.CreateInstance(genericListType); 
+0

Non voglio usare "Elenco" in questo caso, dovrebbe essere qualsiasi oggetto. Il "Tipo openListType = typeof (tipo sconosciuto);" – Deukalion

+0

Non vedo come questa risposta risolva l'OP "utilizzare Activator.CreateInstance() con proprietà {} invece di parametri()?" – Avishek

1

Quando si utilizza l'inizializzazione dell'oggetto, è solo con un costruttore di default (senza parametri), quindi impostando le singole proprietà dopo che l'oggetto è stato costruito.

Il codice di cui sopra è chiuso, ma var non funzionerà qui, poiché si tratta solo di un'inferriazione di tipo in fase di compilazione. Dal momento che si sta già utilizzando la riflessione, si può semplicemente utilizzare System.Object:

object propertyValue = values[p.Name]; 

La chiamata SetValue funzionerà bene con System.Object.

+0

Così come posso usare Activator.CreateInstance con "Object inizializzatore "come argomento? Viene visualizzato un messaggio di errore "Nessun costruttore parametrico definito per questo oggetto". I tipi di proprietà a cui tento di aggiungere valori sono: String, Double, enum, bool. Il tipo su cui non riesce è "String". Non ha un costruttore senza parametri, quindi non posso creare una stringa e aggiungere valore ad essa, ma come può essere dato che posso definire: String str; o String str = "Questa è una stringa"; – Deukalion

+0

@Deukalion Il tipo che stai generando non ha un costruttore senza parametri - quindi non puoi usare questa tecnica con esso ... –

+0

La stringa 'String str =" Foo ";' sintassi è una funzione in linguaggio C#, non una Funzione CLR. –

5

È possibile utilizzare il metodo MakeGenericType per ottenere il tipo generico per un particolare argomento di tipo:

var myObjListType = typeof(List<>).MakeGenericType(myObject.GetType()); 
var myObj = Activator.CreateInstance(myObjListType); 
// MyObj will be an Object variable whose instance is a List<type of myObject> 
+0

Ma diciamo che l'oggetto che creo è un "String, boolean, int, float ..." non necessariamente una classe. Se devo quindi impostare un valore su di esso prima di impostare la proprietà objects sul valore. – Deukalion

+0

Per i tipi di valore non è necessario impostare un valore, hanno automaticamente un valore predefinito valido. Ad esempio, un campo di tipo 'bool' non ha bisogno di essere inizializzato su' false', perché ciò avviene automaticamente. Per le stringhe, iniziano come null. Se vuoi che abbiano un altro valore, come "Fred", devi impostare il loro valore su "Fred". Non 'Person.FirstName = new String (" Fred ");', vedi? –

Problemi correlati