2009-02-23 9 views
37

Tengo una tabla en mi base de datos que utilizo para gestionar las relaciones en mi aplicación. es bastante básico en su naturaleza: parentType, parentId, childType, childId ... todo como enteros. He hecho esta configuración antes, pero lo hice con una configuración de interruptor/caja cuando tenía 6 tablas diferentes que estaba tratando de vincular. Ahora tengo 30 tablas con las que trato de hacer esto y me gustaría poder hacerlo sin tener que escribir 30 entradas de casos en mi comando de cambio.Crear dinámicamente un objeto de <Type>

¿Hay alguna manera de que pueda hacer referencia a una clase .Net usando una cadena? Sé que esto no es válida (porque he intentado varias variaciones de este):

Type t = Type.GetType("WebCore.Models.Page"); 
object page = new t(); 

Yo sé cómo conseguir el tipo de instalación, pero ¿cómo lo uso que sobre la marcha para crear un nuevo ¿objeto?

Respuesta

49

Este enlace debería ayudar:

http://msdn.microsoft.com/en-us/library/system.activator.createinstance(VS.71).aspx

Activator.CreateInstance creará una instancia del tipo especificado.

que podría envolver que en un método genérico de esta manera:

public T GetInstance<T>(string type) 
{ 
    return (T)Activator.CreateInstance(Type.GetType(type)); 
} 
+2

Esto no funcionará si el conjunto que contiene el tipo no está ya cargado en el dominio de la aplicación. –

+3

También para llamar a ese método, entonces el OP debe tener acceso al tipo en tiempo de compilación: la pregunta original preguntó cómo crear una instancia en tiempo de ejecución a partir de una cadena. –

+0

simplemente estoy basando mi respuesta en el ejemplo proporcionado en la pregunta. –

9

que desea utilizar Activator.CreateInstance.

Aquí es un ejemplo de cómo funciona:

using System; 
using System.Runtime.Remoting; 

class Program 
{ 
    static void Main() 
    { 
     ObjectHandle o = Activator.CreateInstance("mscorlib.dll", "System.Int32"); 

     Int32 i = (Int32)o.Unwrap(); 
    } 
} 
11

Si el tipo es conocido por la persona que llama, hay una manera mejor, más rápido que usar Activator.CreateInstance: en lugar puede utilizar una restricción genérica en el método que especifica que tiene un constructor sin parámetros predeterminado.

Haciéndolo de esta manera es seguro y no requiere reflexión.

T CreateType<T>() where T : new() 
{ 
    return new T(); 
} 
+6

No requiere reflexión en el nivel de código fuente; sin embargo, usa Activator.CreateInstance en la IL generada. –

+1

se requiere reflexión porque el OP especificó utilizando una cadena para identificar el Tipo. –

0

suponiendo que tiene el tipo siguiente:

public class Counter<T> 
{ 
    public T Value { get; set; } 
} 

y tienen el conjunto del nombre completo del tipo, se puede construir de la siguiente manera:

string typeName = typeof(Counter<>).AssemblyQualifiedName; 
Type t = Type.GetType(typeName); 

Counter<int> counter = 
    (Counter<int>)Activator.CreateInstance(
    t.MakeGenericType(typeof(int))); 

counter.Value++; 
Console.WriteLine(counter.Value); 
8
public static T GetInstance<T>(params object[] args) 
{ 
    return (T)Activator.CreateInstance(typeof(T), args); 
} 

Utilizaría Activator.CreateInstance() en lugar de transmitir, como el activador h como un constructor para genéricos.

1

Aquí hay una función que escribí que clona un registro de tipo T, utilizando la reflexión. Esta es una aplicación muy simple, yo no manejar tipos de complejos etc.

public static T Clone<T>(T original) 
    { 
     T newObject = (T)Activator.CreateInstance(original.GetType()); 

     foreach (var prop in original.GetType().GetProperties()) 
     { 
      prop.SetValue(newObject, prop.GetValue(original)); 
     } 

     return newObject; 
    } 

Espero que esto pueda ayudar a alguien.

Assaf

Cuestiones relacionadas