tag propiedad personalizar c# interface casting base-class activator

propiedad - tooltip c# button



.NET: no se puede convertir el objeto para interconectar los implementos (8)

Tengo una clase (TabControlH60) que hereda de una clase base (UserControl) e implementa una interfaz (IFrameworkClient). Hago una instancia del objeto utilizando la clase Activator .NET. Con la instancia devuelta, puedo convertir a la clase base UserControl, pero no a la interfaz. La excepción que recibo está debajo del código snipet. ¿Cómo puedo lanzar a la interfaz?

object obj = Activator.CreateInstance(objType); Type[] interfaces = obj.GetType().GetInterfaces(); // contains IFrameworkClient m_Client = (UserControl)obj; // base class cast works IFrameworkClient fc = (IFrameworkClient)obj; // interface cast fails // Note: The (IFrameworkClient)obj cast works fine in the debugger Watch window. {"Unable to cast object of type ''FPG.H60.AFF.TabControlH60'' to type ''FPG.AFF.Interfaces.IFrameworkClient''."}


Algo me dice que tu código de ejemplo está dejando algunas cosas fuera ...

class Program { static void Main(string[] args) { var type = typeof(MyClass); object obj = Activator.CreateInstance(type); Type[] interfaces = obj.GetType().GetInterfaces(); var m_Client = (UserControl)obj; IFrameworkClient fc = (IFrameworkClient)obj; } } public interface IFrameworkClient { } public class UserControl { } public class MyClass : UserControl, IFrameworkClient { }

Esto compila y corre.

Apuesto a que el archivo DLL que contiene la definición de IFrameworkClient aún no se ha cargado antes de que intente realizar el lanzamiento. Esto puede suceder cuando estás usando Activator.CreateInstance.

Intente insertar var forceLoad = typeof(IFrameworkClient); antes del reparto.


Cuando la Interface está en un ensamblaje diferente y obtengo mi clase dinámicamente en run-time en un ensamblaje diferente, la interface casting como su muestra (C # conoce nuestra interfaz como un tipo diferente al que heredó la clase).

Esta es mi técnica simple y útil en estos casos:

Cuando estoy seguro de que mi Class ha heredado de la Interface mencionada (por IFrameworkClient , IFrameworkClient ), escribo una línea mágica de código como esta:

dynamic fc = obj as IFrameworkClient ?? (dynamic) obj;

Por esta técnica puedes:

  • Escriba sus códigos después de esta línea de código para fc en la base de design time en la información de los Interface members y en el sistema de inteligencias del editor.
  • Evita cualquier error de conversión de interfaz en run-time

Notas:

  • Necesitas C# v4 para usar dynamic tipo dynamic
  • Normalmente no me gusta usar tipos dynamic en mis códigos, pero puede ayudarnos en algunos casos como este

Defina la Interfaz IFrameworkClient en el espacio de nombres independiente (debe tener espacio de nombres) del proyecto independiente (biblioteca de clases). Luego, agregue la referencia de la biblioteca de clases al proyecto de Control y al proyecto principal


En mi caso tuve que agregar un evento de compilación para copiar la DLL necesaria ya que estaba creando instancias y asignándolas a tipos de interfaz en tiempo de ejecución. De lo contrario, la DLL cargada podría no ser la DLL más actualizada y, por lo tanto, podría no convertirse en la interfaz.

La razón por la que usé eventos de compilación en este caso (en lugar de agregar la DLL como referencia) es que la arquitectura es tal que la aplicación principal solo debe hacer referencia a los tipos de interfaz, y todo lo demás debe cargarse dinámicamente.

TLDR; En el caso de cargar tipos dinámicamente desde otra DLL, asegúrese de copiar la versión más reciente de esa DLL en el directorio bin utilizando eventos de compilación, de lo contrario, la conversión no funcionará cuando parezca que debería hacerlo.


La causa más probable aquí es que IFrameworkClient es de un ensamblaje diferente en los dos casos y, por lo tanto, es un tipo .NET diferente. Incluso si es el mismo código, puede ser un tipo diferente.

Compruebe el AssemblyQualifiedName . Tenga en cuenta también que si está cargando este ensamblaje con reflexión, puede obtener un tipo diferente incluso con el mismo AssemblyQualifiedName , gracias al contexto de carga.


La conversión no está funcionando porque está intentando convertir desde el tipo de object a la interfaz. Si reemplaza la línea de colada de la interfaz con:

IFrameworkClient fc = (IFrameworkClient)m_Client;

Funcionará.

Alternativamente, estoy ligeramente seguro de que podría hacer la conversión del objeto a la interfaz con el operador as .

Consulte este artículo para obtener más información: http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx

Una pieza más del rompecabezas. Las interfaces no se derivan del object : http://blogs.msdn.com/ericlippert/archive/2009/08/06/not-everything-derives-from-object.aspx


Si la clase FPG.H60.AFF.TabControlH60 implementa realmente IFrameworkClient, no debería haber ninguna razón para que esto falle. Lo único en lo que puedo pensar que causa esta excepción es si el ensamblaje que contiene IFrameworkClient tiene un nombre seguro y el objeto Tab Control hace referencia a una versión diferente del ensamblado que contiene o si está usando una interfaz diferente con el nombre IFrameworkClient.


Tengo los mismos problemas con una biblioteca mía que proporciona funcionalidad de "plugin" ... Finalmente lo tengo funcionando ...

Aquí estaba mi problema: tenía un ensamblaje principal que usa complementos, un ensamblaje con el complemento (Plugin.dll) Y (importante) otro ensamblado que proporciona la funcionalidad del complemento (Library.dll).

El Plugin.dll hizo referencia al conjunto principal (para poder extenderlo) y el Library.dll con la función de complemento. - Los binarios han llegado a un directorio "./Plugins" relativo al ensamblaje principal.

El ensamblaje principal también hizo referencia a la función de complemento. Se escribe el montaje para usar el "PluginManager". Este "PluginManager" obtiene una ruta y carga todos los archivos * .dll a través de la reflexión para analizar si hay una interfaz "IPlugin" (que también proviene de Library.dll).

Cada vez que llamaba a PluginManager para cargar los complementos, no podía enviarlos a "IPlugin" aunque ellos lo implementaran.

Casi me enojo, pero luego descubrí todo el problema. Al compilar el complemento no solo estaba el "Plugin.dll" sino el "Library.dll" escrito en el directorio "./Plugins". Al cargar accidentalmente el "Library.dll" cada vez con mi PluginManager, ahora tenía dos tipos de "IPlugin", uno en el "Library.dll" real que se usa desde el ensamblaje principal y otro que se cargó a través de mi PluginManager, y ¡Aquellos eran incompatibles!

Atención: si simplemente no carga "./Plugins/Library.dll", sin embargo, se encontrará con el problema, porque si carga "Plugin.dll" que hace referencia a "Library.dll", entonces solo usará el que está en el mismo directorio. .. TILT ... !! Mi PluginManager ahora solo elimina "Library.dll" donde lo encuentra.

La clave es: ¡Asegúrese de no acceder a dos ensamblajes en contextos diferentes!