C # Arquitectura de complementos con interfaces compartidas entre complementos

Dividí mi problema en una versión corta y larga para las personas con poco tiempo disponible.

Version corta

Necesito algo de arquitectura para un sistema con complementos de proveedores y consumidores. Los proveedores deben implementar IProvider entre interfaces y los consumidores deben implementar IConsumer. La aplicación en ejecución solo debe conocer IProvider e IConsumer. Una implementación de consumidor puede preguntarle al ensamblaje ejecutante (por medio de un ServiceProcessor) qué proveedores implementan InterfaceX y recupera una Lista. Estos objetos de IProvider se deben convertir a InterfaceX (en el consumidor) para poder enganchar al consumidor en algunos eventos que InterfaceX define. Esto fallará porque el ensamblaje en ejecución de alguna manera no conoce este tipo de InterfaceX (falla la conversión). La solución sería incluir InterfaceX en algún ensamblado que los complementos y la referencia de ensamblaje en ejecución, pero esto debería significar una recompilación para cada nuevo par proveedor / consumidor y es altamente indeseable.

¿Alguna sugerencia

Versión larga

Estoy desarrollando algún tipo de servicio genérico que utilizará complementos para lograr un mayor nivel de reutilización. El servicio consiste en algún tipo de implementación de patrón de Observador utilizando Proveedores y Consumidores. Tanto los proveedores como los consumidores deben ser complementos para la aplicación principal. Permítanme explicar primero cómo funciona el servicio enumerando los proyectos que tengo en mi solución.

Proyecto A: un proyecto de servicio de Windows para alojar todos los complementos y la funcionalidad básica. Se utiliza un proyecto TestGUI Windows Forms para una depuración más fácil. Una instancia de la clase ServiceProcessor del Proyecto B está haciendo las cosas relacionadas con el complemento. Las subcarpetas "Consumidores" y "Proveedores" de este proyecto contienen subcarpetas donde cada subcarpeta contiene un complemento de consumidor o proveedor de manera ensamblable respectivamente.

Proyecto B: una biblioteca de clases que contiene la clase ServiceProcessor (que realiza la carga y distribución de complementos entre complementos, etc.), IConsumer e IProvider.

Project C: una biblioteca de clase, vinculada al proyecto B, que consta de TestConsumer (implementando IConsumer) y TestProvider (implementando IProvider). TestProvider implementa una interfaz adicional (ITest, derivada de IProvider).

El objetivo aquí es que un complemento de Consumidor puede preguntarle al Proveedor de servicios qué Proveedores (que implementa al menos IProvider) tiene). Los objetos IProvider devueltos se deben convertir a la otra interfaz que implementa (ITest) en la implementación de IConsumer para que el consumidor pueda conectar controladores de eventos a los eventos ITest.

Cuando se inicia el proyecto A, se cargan las subcarpetas que contienen los complementos de consumidor y proveedor. A continuación se presentan algunos problemas que he encontrado hasta ahora e intenté resolver.

La interfaz que ITest solía residir en el Proyecto C, ya que esto solo se aplica a los métodos y eventos que TestProvider y TestConsumer conocen. La idea general es mantener el proyecto A simple y sin darse cuenta de lo que hacen los complementos entre sí.

Con ITest en el proyecto C allí y el código en el método Initialize del TestConsumer que convierte el IProvider en ITest (esto no debería fallar en una biblioteca de una sola clase cuando un objeto que implementa ITest se conoce como un objeto IConsumer) un error de conversión no válido ocurrir. Este error puede resolverse colocando la interfaz ITest en el proyecto B al que hace referencia también el proyecto A. Sin embargo, es muy no deseado, ya que necesitamos recompilar el proyecto A cuando se construye una nueva interfaz.

Traté de poner ITest en una biblioteca de una sola clase a la que hace referencia el proyecto C únicamente, ya que solo el proveedor y el consumidor deben conocer esta interfaz, pero sin éxito: al cargar el complemento, el CLR indica que no se pudo encontrar el proyecto al que se hace referencia . Esto podría resolverse enganchando el evento AssemblyResolve del AppDomain actual, pero de alguna manera esto también parece no deseado. ITest volvió al Proyecto B nuevamente.

Traté de dividir el proyecto C en un proyecto separado para el consumidor y el proveedor y ambos cargaron los ensamblajes que funcionan bien: ambos ensamblados residen en la colección Assemblies o en el AppDomain actual: Ensamblado encontrado: Datamex.Projects.Polaris.Testing. Proveedores, Versión = 1.0.0.0, Cultura = neutral, PublicKeyToken = 2813de212e2efcd3 Asamblea encontrada: Datamex.Projects.Polaris.Testing.Consumers, Versión = 1.0.0.0, Cultura = neutral, PublicKeyToken = ea5901de8cdcb258

Desde que el Consumidor utiliza el Proveedor, se hizo una referencia del Consumidor al Proveedor. Ahora, el evento AssemblyResolve se activó nuevamente indicando que necesita el siguiente archivo: AssemblyName = Datamex.Projects.Polaris.Testing.Providers, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = 2813de212e2efcd3

Mis preguntas: ¿por qué es esto? Este archivo ya está cargado ¿verdad? ¿Por qué es imposible el envío de IProvider a alguna interfaz que sé que implementa? Probablemente esto se deba a que el programa en ejecución no conoce esta interfaz, pero ¿no se puede cargar dinámicamente?

Mi objetivo final: los complementos del consumidor preguntan al ServiceProcessor qué proveedores tiene que implementan la interfaz x. Los proveedores se pueden enviar a esta interfaz x, sin que el ensamblado esté al tanto de la interfaz x.

¿Alguien que pueda ayudar?

Gracias de antemano, Erik

Respuestas a la pregunta(5)

Su respuesta a la pregunta