2012-05-22 16 views
6

Actualmente estoy usando Generics para hacer algunos métodos dinámicos, como crear un objeto y llenar las propiedades con valores.Creando variables genéricas de un tipo - ¿Cómo? O use Activator.CreateInstance() con propiedades {} en lugar de parameters()?

¿Hay alguna manera de crear "genéricamente" el genérico sin saber el tipo? Por ejemplo:

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

es una forma predefinied, pero

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

no funciona ... Pero se puede?

Esto no está funcionando (¿Hay un enfoque similar que funciona?)

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

Así, en pocas palabras: ¿Cómo tomar un "tipo" y crear un objeto a partir de que sin el uso de los genéricos? Hasta ahora solo he usado Genéricos en los métodos, pero ¿es posible usar el mismo método en las variables? Tengo que definir un Genérico (T) antes del método, entonces ¿puedo hacer lo mismo con las variables antes de "crearlas"?

... o cómo usar "Activador" para crear un objeto con Propiedades en lugar de Parámetros. Como se hace aquí:

// Con los parámetros de valores

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

// Con propiedades

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

Respuesta

13

Puede utilizar MakeGenericType:

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

No quiero usar "Lista" en este caso, debe ser cualquier objeto. El "Tipo openListType = typeof (tipo desconocido);" – Deukalion

+0

No veo cómo esta respuesta resuelve el OP "use Activator.CreateInstance() con propiedades {} en lugar de parameters()?" – Avishek

1

Cuando se utiliza el objeto iniciador, es simplemente utilizando un constructor por defecto (sin parámetros), luego establecer las propiedades individuales después de construir el objeto.

El código anterior está cerca, pero var no funcionará aquí, ya que es solo una inferrencia tipo compilación. Puesto que usted ya está usando la reflexión, sólo puede utilizar System.Object:

object propertyValue = values[p.Name]; 

La llamada SetValue no tendrán ningún problema con System.Object.

+0

Entonces, ¿cómo puedo usar Activator.CreateInstance con "Objeto inicializador "como argumento? Aparece un error que dice "Ningún constructor sin parámetros definido para este objeto". Los tipos de propiedades a las que intento agregar valores son: String, Double, enum, bool. El tipo en el que falla es "Cadena". No tiene un constructor sin parámetros, por lo que no puedo crear una Cadena y agregarle valor, pero ¿cómo puede ser eso ya que puedo definir: String str; o String str = "Esto es una cadena"; – Deukalion

+0

@Deukalion El tipo que está generando no tiene un constructor sin parámetros, por lo que no puede usar esta técnica con él ... –

+0

La sintaxis 'String str =" Foo ";' es una característica del lenguaje C#, no una Característica CLR –

5

Usted puede utilizar el método MakeGenericType para obtener el tipo genérico para un argumento de tipo particular:

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

Pero digamos que el objeto que creo es un "String, boolean, int, float ..." no necesariamente una clase. Si luego necesito establecer un valor antes de establecer la propiedad de los objetos al valor. – Deukalion

+0

Para los tipos de valor, no es necesario establecer un valor; automáticamente tienen un valor predeterminado válido. Por ejemplo, un campo de tipo 'bool' no necesita ser inicializado a' falso', porque eso ocurre automáticamente. Para cuerdas, comienzan nulo. Si desea que tengan otro valor, como "Fred", debe establecer su valor en "Fred". No 'Person.FirstName = new String (" Fred ");', ¿ves? –

Cuestiones relacionadas