2010-02-18 22 views
5

Supongamos que tengo un método de fábrica, que quiere construir una instancia de un tipo elegido en tiempo de ejecución a través de la reflexión. Supongamos además que mi método de fábrica es un código genérico que no hace referencia directamente al ensamblaje que contiene el tipo especificado, aunque se ejecutará desde una aplicación que tenga referenciado el ensamblaje necesario.¿Cómo puedo obtener un tipo de un conjunto referenciado a través de la reflexión

¿Cómo hago para escribir un código que pueda encontrar este tipo? Si hago lo siguiente

public object CreateInstance(string typeName) 
{ 
    Type desiredType = Assembly.GetExecutingAssembly().GetType(typename); 

    // Instantiate the type... 
} 

esto parece fallar porque el tipo no está definido en el ensamblaje en ejecución. Si pudiera obtener todas las asambleas disponibles en tiempo de ejecución, podría iterar sobre ellas y encontrar cuál contiene el tipo que deseo. Pero no puedo ver una manera de hacer eso. AppDomain.CurrentDomain.GetAssemblies() parece prometedor, pero no devuelve todos los ensamblajes a los que me he referido en mi proyecto.

Editar: Varias personas han señalado que necesito cargar el conjunto. El problema es que este fragmento de código no sabe qué ensamblaje debe cargar, ya que intento escribir este código de manera que no dependa de los otros ensamblajes.

Deliberadamente omití los detalles de typeName, ya que el mapeo de una cadena a otra es realmente más complicado en mi código real. De hecho, el tipo se identifica mediante un atributo personalizado que contiene la cadena especificada, pero si puedo obtener una lista de tipos, no tengo problemas para restringir la lista al tipo deseado.

+0

¿Cuál es el valor en typeName? ¿Es el nombre completo? –

Respuesta

9

La llamada a AppDomain.CurrentDomain.GetAssemblies() solo devuelve el conjunto de DLL que están actualmente cargadas en el AppDomain. Las DLL se cargan en un proceso CLR bajo demanda; por lo tanto, no incluirá todas las DLL a las que se hace referencia en su proyecto hasta que realmente se use una.

Lo que podría hacer, sin embargo, es forzar el ensamblaje en el proceso utilizando una expresión typeof. Por ejemplo

var force1 = typeof(SomeTypeInTheProject).Assembly; 
var force2 = typeof(SomeTypeInProject2).Assembly; 
+0

Gracias, parece que funciona, y como todos los tipos posibles están en el mismo ensamblaje, solo tengo que hacerlo para un tipo. Sin embargo, se siente bastante feo. –

2

AppDomain.CurrentDomain.GetAssemblies() solo devuelve los conjuntos cargados. Por lo tanto, debe cargar el ensamblaje al que se hace referencia si aún no se ha cargado.

10

Usted podría utilizar GetReferencedAssemblies y recorrer todos los tipos hasta encontrar el tipo que usted está buscando.

var t = Assembly 
    .GetExecutingAssembly() 
    .GetReferencedAssemblies() 
    .Select(x => Assembly.Load(x)) 
    .SelectMany(x => x.GetTypes()).First(x => x.FullName == typeName); 

Aunque podría no ser el más eficiente. Por otra parte, usted es usando la reflexión.

+0

Buena idea. No funciona para mí, ya que el ensamblaje no se referencia directamente, pero el ensamblado llamante hace referencia indirectamente al mismo; presumiblemente, podría encontrarlo llamando recursivamente a .GetReferencedAssemblies() en cada uno de los ensamblados encontrados (y comenzando por .GetEntryAssembly() en lugar de .GetExecutingAssembly()). Y sí, no es genial para el rendimiento, pero eso está bien para mí, ya que es código de inicio y solo se ejecuta una vez. –

Cuestiones relacionadas