c# - tecnológicos - Cómo moldear adecuadamente los objetos creados a través de la reflexión
el uso excesivo de aparatos tecnológicos afecta su salud (7)
Estoy tratando de concentrarme en la reflexión, así que decidí agregar capacidad de complemento a un programa que estoy escribiendo. La única forma de entender un concepto es ensuciarse los dedos y escribir el código, así que decidí crear una biblioteca de interfaz simple que constaba de las interfaces IPlugin e IHost, una biblioteca de implementación de complementos de clases que implementan IPlugin y una sencilla proyecto de consola que ejemplifica la clase de implementación IHost que hace un trabajo simple con los objetos del complemento.
Usando la reflexión, quería iterar a través de los tipos que figuran dentro de mi plugin implementation dll y crear instancias de tipos. Pude instanciar con éxito las clases con este código, pero no pude convertir el objeto creado a la interfaz.
Intenté este código pero no pude lanzar el objeto o como esperaba. Pasé por el proceso con el depurador y se llamó al constructor adecuado. El objeto Quickwatching o me mostró que tenía los campos y las propiedades que esperaba ver en la clase de implementación.
loop through assemblies
loop through types in assembly
// Filter out unwanted types
if (!type.IsClass || type.IsNotPublic || type.IsAbstract )
continue;
// This successfully created the right object
object o = Activator.CreateInstance(type);
// This threw an Invalid Cast Exception or returned null for an "as" cast
// even though the object implemented IPlugin
IPlugin i = (IPlugin) o;
Hice que el código funcione con esto.
using System.Runtime.Remoting;
ObjectHandle oh = Activator.CreateInstance(assembly.FullName, type.FullName);
// This worked as I intended
IPlugin i = (IPlugin) oh.Unwrap();
i.DoStuff();
Aquí están mis preguntas:
- Activator.CreateInstance (Type t) devuelve un objeto, pero no pude convertir el objeto a una interfaz que el objeto implementó. ¿Por qué?
- ¿Debo haber estado usando una sobrecarga diferente de CreateInstance ()?
- ¿Cuáles son los consejos y trucos relacionados con la reflexión?
- ¿Hay alguna parte crucial de la reflexión que no estoy obteniendo?
¿Tu tipo no es público? Si es así, llama a la sobrecarga que toma un booleano:
Activator.CreateInstance(type, true);
Además, en su primer ejemplo, vea si o es nulo y si no, imprima o.GetType (). Nombre para ver lo que realmente es.
Estoy adivinando aquí porque de su código no es obvio dónde tiene definición de la interfaz IPlugin, pero si no puede convertir su aplicación host, probablemente tenga la interfaz IPlugin en su ensamblado host y luego al mismo tiempo en su ensamblaje de complemento Esto no funcionará
Lo más fácil es hacer que esto funcione para tener la interfaz IPlugin marcada como pública en su ensamblado de host y luego tener su ensamblado de aplicación de host de referencia del ensamblado de complementos, para que ambos ensambles tengan acceso a la misma interfaz .
¡Solo estaba tratando de resolver esto yo mismo y logré encontrar la respuesta!
Tenía 3 proyectos diferentes de C #
- A - Proyecto de interfaz de complementos
- B - Proyecto de host exe -> referencias A
- C - Proyecto de implementación de complementos -> referencias A
Estaba obteniendo el error de conversión hasta que cambié el nombre del ensamblado para mi proyecto de interfaz de complementos para que coincida con el espacio de nombres de lo que estaba tratando de transmitir.
P.ej
IPluginModule pluginModule = (IPluginModule)Activator.CreateInstance(curType);
estaba fallando porque el ensamblado en el que se definió la interfaz IPluginModule se llamaba ''Common'', sin embargo, The-type-I estaba volviendo a ''Blah.Plugins.Common.IPluginModule''.
Cambié el nombre del ensamblado para que el proyecto de interfaz fuera ''Blah.Plugins.Common'' significaba que el reparto tenía éxito.
Espero que esta explicación ayude a alguien. Volver al código ...
hmmm ... Si está utilizando Assembly.LoadFrom para cargar su ensamblaje intente cambiarlo Assembly.LoadFile en su lugar.
Trabajó para mi
Desde aquí: http://www.eggheadcafe.com/community/aspnet/2/10036776/solution-found.aspx
El enlace a egghead anterior es la solución principal al problema use Assembly.LoadFile () en lugar de .LoadFrom ()
@ Haacked
Traté de mantener el pseudocódigo simple. foreach ocupa mucho espacio y llaves. Lo aclaré
o.GetType (). FullName devuelve Plugins.Multiply, que es el objeto esperado. Plugins.Multiply implementa IPlugin. Pasé por el proceso en el depurador unas cuantas veces hasta que me rendí por la noche. No pude entender por qué no pude lanzarlo porque vi cómo el constructor disparaba hasta que me enojé por todo el desastre. Volví a hacerlo esta noche y lo hice funcionar, pero todavía no entiendo por qué falló el reparto en el primer bloque de código. El segundo bloque de código funciona, pero me parece desagradable.
Lo clavaste en la nariz. Mi diseño original tenía tres ensamblajes diferentes con la implementación del host y del complemento que hacía referencia al ensamblaje de la interfaz del complemento.
Probé una solución separada con un ensamblado de implementación e interfaz de host y un ensamblado de implementación de complemento. Dentro de esa solución, el código en el primer bloque funcionó como se esperaba.
Me ha dado un poco más para pensar, porque no entiendo muy bien por qué dos ensamblados que hacen referencia a un ensamblaje común no obtienen el mismo tipo del conjunto común.