2011-11-21 16 views
6

Necesito obtener una instancia de un tipo cuyo nombre y nombre de ensamblado tendré en tiempo de ejecución. Sé de antemano que el tipo tendrá un constructor sin parámetros. ¿Cuál es la forma más fácil de hacer esto?Cómo cargar un tipo del nombre del tipo y el nombre del ensamblado

Es waaaaaaay más difícil de lo que esperaba.

Editar: No estoy si esto es relevante, pero se hará referencia al conjunto. No necesito cargarlo desde el disco o algo así.

Respuesta

2

La siguiente debería ser suficiente:

var assmebly = Assembly.Load("FullyQualifiedAssemblyName"); 
var type = assmebly.GetType("FullTypeName"); 
var instance = Activator.CreateInstance(type); 
5

De MSDN:

Activator.CreateInstance Método (String, String)

crea una instancia del tipo cuyo nombre se especifica , utilizando el ensamblado nombrado y el constructor predeterminado.

public static ObjectHandle CreateInstance(
    string assemblyName, 
    string typeName 
) 

Ejemplo:

var assemblyName = 
    "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; 

var typeName = "System.Net.WebClient"; 

var instance = Activator.CreateInstance(assemblyName, typeName).Unwrap(); 
+0

Lo he intentado y he tenido problemas con él, de ahí mi pregunta. – David

+0

@David: ¿Cuál fue el problema? He agregado un ejemplo de trabajo; ¿Eso ayuda? – dtb

+1

Es posible que no funcionara porque no estaba especificando Version, Culture y PublicKeyToken para el ensamblaje. Pero no hay ejemplos que parecen hacer esto. – David

2
Type referencedType = typeof(AReferencedType); 
AReferencedType instance = Activator.CreateInstance<AReferencedType>(); 

or 

Type type = Type.GetType("Type's full name"); 
object instance = Activator.CreateInstance(type); 
+0

En el segundo fragmento, ¿GetType no requiere también el nombre del ensamblado? Pensé que sí. – David

+0

@David, no si usa el nombre completo de tipo http://msdn.microsoft.com/en-us/library/w3f99sx1.aspx –

+0

Bueno, ese tipo de necesidad necesita el nombre del ensamblado. De todos modos, todo está bien. – David

3

Si hace referencia a System.Web.dll no es un problema para ti, no es la l poco conocido BuildManager.GetType Method que es bastante eficiente. Ni siquiera requiere el nombre del ensamblado porque escanea los tipos en ensambles en la ruta de ejecución de AppDomain actual.

Así que el código sería:

object instance = Activator.CreateInstance(BuildManager.GetType("MyNamespace.MyClass", true)); 
+0

Poco conocido de hecho. Gracias por el consejo. – David

+0

Muy útil y práctico. Sería aún más útil si core> _ < – user2864740

2
Activator.CreateInstance(Type.GetType("System.Int32")); 

Activator

Type

+0

Solo tengo los nombres del ensamblado y la clase en tiempo de ejecución. – David

1

Aquí hay algo que funciona utilizando la fantasía dynamic palabra clave. Tendrá que hacer referencia a la otra clase para que pase la prueba, o usar un evento de compilación para copiar sobre la DLL integrada.

namespace TestLibrary 
{ 
    [TestFixture] 
    public class Tests 
    { 
     [Test] 
     public void FileCheck() 
     { 
      dynamic otherClass = 
       AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap("OtherLibrary.dll",     
        "Prefix.OtherLibrary.SomeClass"); 
      otherClass.SayHello(); // look, ma! no casting or interfaces! 
     } 
    } 
} 

namespace Prefix.OtherLibrary 
{ 
    public class SomeClass 
    { 
     public void SayHello() 
     { 
      Console.WriteLine("Hello, world."); 
     } 
    } 
} 

A diferencia Activator, AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap toma un nombre de fichero como primer argumento en lugar de un especificador de tipo. Esto a veces es útil, especialmente cuando no le importa el nombre fuerte del ensamblaje.

+0

Enfoque interesante. ¿Te conozco? – David

Cuestiones relacionadas