Ich versuche, DI (mit Autofac) in eine vorhandene Windows Forms-Anwendung einzuführen.DI (Autofac) in einer Plugin-Architektur: Ist ein eigener DI-Container pro Plug-In OK?
Diese Anwendung verfügt über eine grundlegende Plug-in-Architektur, bei der jedes Plugin sein eigenes Formular anzeigt. Beim Start der Anwendung Scans Baugruppen für Typen registriert, die IPlugin
implementieren, und aktiviert dann diese mit Activator.CreateInstance
:
public interface IPlugin
{
Form MainForm { get; }
}
ich kann nicht Änderung dieses vorgegebenen Rahmens. Das bedeutet, dass jede Plugin-Klasse durch Nicht-DI-Mittel instanziiert wird, und es scheint mir, dass ich deshalb einen separaten DI-Container für jedes Plugin starten muss.
Meine Frage ist, erstellt eine separate ContainerBuilder
und Container pro Plugin OK und noch einigermaßen effizient? (Es wird ca. 10 verschiedene Plugins geben.) Oder sollte es nur einen DI-Container für die gesamte Anwendung geben?
Ich habe einige Beispielcode meiner aktuellen Lösung unten zur Verfügung gestellt.
using Autofac;
using System.Windows.Forms;
public class Plugin : IPlugin // instantiated by Activator
{
public Form MainForm { get; private set; }
public Plugin() // parameter-less constructor required by plugin framework
{
var builder = new ContainerBuilder();
builder.RegisterModule(new Configuration());
var container = builder.Build();
MainForm = container.Resolve<MainForm>();
//^preferred to new MainForm(...) because this way, I can take
// advantage of having dependencies auto-wired by the container.
}
}
internal class Configuration : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<MainForm>().SingleInstance();
// ... more plugin-specific registrations go here...
}
}
internal class MainForm : Form { /* ... */ }
Ich bin auch nicht sicher, ob ein Container in der Plugin-Konstruktor erstellen und dann einfach über sie zu vergessen, aber verlassen sie Auto-Verkabelung im Hintergrund zu tun, OK ist?
Danke für die Antwort, @Mark. Wenn ich Sie richtig verstehe, folgt mein Beispielcode bereits dem RRR-Muster ... richtig? (Mit der Ausnahme, dass ich den Container nicht freigebe, da er mindestens so lange am Leben bleiben muss wie die Root-Komponente 'MainForm'. Ich denke, der beste Weg wäre, Plugins' IDisposable' zu machen und zu veröffentlichen Der Container in der 'Dispose'-Methode.) – stakx
Es gibt nichts in Ihrem Code, das darauf hinweist, dass Sie RRR nicht befolgen, aber es ist schwer zu sagen. Beachten Sie in jedem Fall, dass der Lifestyle von SingleInstance nur einen containerspezifischen Singleton definiert. Es ist kein echtes Singleton, daher können Sie das MainForm nicht auf diese Weise teilen. –