5

Estoy diseñando un plugin framework simple para una aplicación .NET 3.5 (WinForms).Un contenedor de IoC simple para un pequeño sistema de complemento

Nuestra aplicación actual necesita comenzar a soportar carga dinámica y "enganche" de diferentes "complementos"/"extensiones" que son desconocidos para la aplicación en tiempo de compilación.

Estas extensiones se "engancharán" en diferentes áreas de la aplicación, como por ejemplo como manejadores de eventos de ciertas clases.

Por ejemplo (simplificado):

public class SomeSystem 
{ 
    public event Action<string> Completed; 

    public event Action<string> Failed; 

    public event Action<string> Stopped; 
} 

Uno de los usos caso me gustaría tener es para los desarrolladores ser capaz de definir manejadores para este tipo de eventos en un montaje de plug-in, sin tener la aplicación saber sobre ellos .

Según mi conocimiento, los contenedores IoC permiten descubrir dinámicamente objetos en tiempo de ejecución y registrarlos en un contenedor.

¿Es un contenedor IoC capaz de hacer este enganche en varios eventos para mí? ¿O es más fácil hacer esta tarea sin ese marco?

¿Cómo se puede diseñar cómo integrar un contenedor IoC para una tarea como esta? (supongamos que hay múltiples puntos de extensión, como diferentes eventos que pueden usarse para registrarse).

Algunas preguntas me encontré preguntando:

  1. ¿Es común que el propio plugin ofrece un método Registro para hacer el registro?
  2. ¿Debería el IoC hacer el registro? (¿cómo se hace normalmente?)
  3. ¿Cómo se pueden definir fácilmente los puntos de extensión cuando se usa un contenedor IoC?

Respuesta

5

Probablemente desee consultar MEF. Permite todas las cosas que has preguntado. La terminología que usa (ComposableParts, Exports, etc.) inicialmente es confusa, pero es muy fácil de usar.

¿Es común que el complemento ofrezca un método de registro para realizar el registro ?

MEF hace que la aplicación haga el trabajo de buscar y registrar complementos. El complemento solo necesita implementar una interfaz que indique "Soy un complemento que puede hacer X".

¿Debería hacer la inscripción el IoC? (¿cómo se hace normalmente?)

Una aplicación que consumirá complementos MEF puede especificar cómo cargará los complementos. Esto podría ser buscando en un directorio DLL, leyendo el archivo de configuración para una lista de nombres de ensamblado, verificando el GAC, cualquier cosa. Es totalmente extensible (en el que se puede escribir sus propias clases de búsqueda)

¿Cómo puede definirse puntos de extensión fácilmente cuando se utiliza un contenedor IoC ?

MEF usa interfaces para definir un Contrato entre la aplicación y el complemento.

+0

Con MEF, cada "parte" es una aplicación de alguna de las interfaces. Esto significa que para cada punto de extensibilidad, ¿debería crearse una nueva interfaz? Por ejemplo, tengo 3 eventos: OnA, OnB, OnC. ¿Cómo habilito los complementos para que se enganchen a estos eventos con MEF? (sin definir 3 interfaces diferentes). –

+0

Realmente no entiendo la pregunta: si OnA, OnB y OnC están lógicamente asociados de tal manera que puedan formar parte de una interfaz única, conviértanla en una única interfaz. Si no están asociados, hágalos parte de interfaces separadas. ¿O he entendido mal tu pregunta? –

+0

Quiero decir, si tengo muchos eventos diferentes en los que quiero registrarme dinámicamente, cada uno de ellos debe definir explícitamente que están importando una determinada interfaz. Esto significa que tengo que definir 3 interfaces diferentes (una para cada tipo de evento). Digamos que tengo 1 interfaz y 3 eventos importan esta implementación de interfaz. Los 3 eventos importarán todas las implementaciones, que no es lo que busco. –

0

Esta respuesta será específica para mi contenedor.

Nuestra aplicación actual necesita comenzar a soportar carga dinámica y "enganche" de diferentes "complementos"/"extensiones" que son desconocidos para la aplicación en tiempo de compilación.

Para poder hacer eso, debe definir algunas interfaces de extensión que coloca en una biblioteca de clases que se compartirá entre su aplicación y todos sus complementos.

Por ejemplo, si desea que sus aplicaciones para ser capaz de añadir material al menú de la aplicación se puede crear la siguiente interfaz:

class ApplicationMenu 
{ 
    // The "File" menu 
    IMenuItem File { get; } 
} 

interface IMenuRegistrar 
{ 
    void Register(ApplicationMenu menu); 
} 

Lo que significa que su plugin puede crear la siguiente clase:

[Component] 
public class CoolPluginMenuRegistrar : IMenuRegistrar 
{ 
    public void Register(ApplicationMenu menu) 
    { 
     menu.File.Add("mnuMyPluginMenuName", "Load jokes"); 
    } 
} 

Mi contenedor utiliza el atributo [Component] para que pueda descubrir y registrar automáticamente las clases por usted.

Todo lo que necesita hacer para registrar a todos los puntos de extensión como la de arriba es la siguiente:

public class Program 
{ 
    public static void Main(string[] args) 
    { 
     var registrar = new ContainerRegistrar(); 
     registrar.RegisterComponents(Lifetime.Transient, Environment.CurrentDirectory, "MyApp.Plugin.*.dll"); 
     var container = registrar.Build(); 

     // all extension points have been loaded. To load all menu extensions simply do something like: 

     var menu = GetMainMenu(); 
     foreach (var registrar in container.ResolveAll<IMenuRegistrar>()) 
     { 
      registrar.Register(menu); 
     } 
    } 
} 

Estas extensiones serían "enganchado" en diferentes áreas de la aplicación, tales como ADED como controladores de eventos de ciertas clases. Por lo que sé, los contenedores IoC permiten descubrir dinámicamente objetos en tiempo de ejecución y registrarlos en un contenedor.

Yep. Usted obtiene todo eso.

¿Es un contenedor IoC capaz de hacer este enganche en varios eventos para mí? ¿O es más fácil hacer esta tarea sin ese marco?

Sí. Obtuve un mecanismo de evento incorporado. Coloque las clases de eventos (clases .NET regulares en bibliotecas de clases compartidas). El simplemente suscribirse en ellos mediante la implementación de una interfaz:

[Component] 
public class ReplyEmailNotification : ISubscriberOf<ReplyPosted> 
{ 
    ISmtpClient _client; 
    IUserQueries _userQueries; 

    public ReplyEmailNotification(ISmtpClient client, IUserQueries userQueries) 
    { 
     _client = client; 
     _userQueries = userQueries; 
    } 

    public void Invoke(ReplyPosted e) 
    { 
     var user = _userQueries.Get(e.PosterId); 
     _client.Send(new MailMessage(user.Email, "bla bla")); 
    } 
} 

y publicar eventos:

DomainEvent.Publish(new ReplyPosted(user.Id, "This is a subject")); 

Los eventos pueden ser manejados por ningún plugin, siempre y cuando:

  1. puede acceder la clase de evento
  2. Se han registrado en el contenedor ([Component] o registro manual)
  3. Implementa ISubscriberOf<T>

¿Es común que el propio plugin ofrece un método Registro para hacer el registro?

Yep. A través de diferentes interfaces que se definen como puntos de extensión en un conjunto compartido.

¿Debería hacer la inscripción el IoC? (¿cómo se hace eso generalmente?)

Sí. Si el contenedor lo proporciona.

¿Cómo se pueden definir fácilmente los puntos de extensión cuando se utiliza un contenedor IoC?

Usted puede leer sobre ello con más detalle aquí: http://www.codeproject.com/Articles/440665/Having-fun-with-Griffin-Container

Cuestiones relacionadas