Abhängigkeitsinjektion im Apache Ignite.NET-Dienst

Bei der Entwicklung verschiedener Anwendungen, die die beliebte Castle Windsor- Bibliothek zum Einfügen von Abhängigkeiten und Apache Ignite.NET als „Schlüssel“ verwenden, der die Tür zum Cloud-Computing öffnet, stieß ich auf eine leichte Unannehmlichkeit: Ich hatte keine Möglichkeit, die Abhängigkeit in den gestarteten Dienst einzufügen über das sogenannte Service Grid.

Der Grund dafür ist ziemlich alltäglich. Apache Ignite.NET serialisiert den Dienst und sendet ihn an einen der verfügbaren Server, wo er deserialisiert und gestartet wird. Da dieser Prozess in keiner Weise eine Ahnung von Castle Windsor hat, bekommen wir, was wir bekommen.

Um dieses Problem zu lösen, müssen wir ein Plug-In für Apache Ignite.NET erstellen, das einen Container erhält, der für die Implementierung von Abhängigkeiten verantwortlich ist, und dem Dienst die Möglichkeit bietet, darauf zuzugreifen, um ein Objekt zu empfangen.

Zunächst werden wir eine zusätzliche Abstraktionsebene für den Container einführen, die die Abhängigkeitsinjektion ermöglicht, damit wir in Zukunft die Implementierung problemlos auf eine andere ändern können:

public interface IContainer { T Resolve<T>(); } 

 public class DependencyInjectionContainer : IContainer { protected IKernel Kernel { get; set; } public DependencyInjectionContainer(IKernel kernel) { Kernel = kernel; } public T Resolve<T>() { return Kernel.Resolve<T>(); } } 

 public class DependencyInjectionInstaller : IWindsorInstaller { public void Install(IWindsorContainer container, IConfigurationStore store) { container.Register( Component .For<IContainer>() .ImplementedBy<DependencyInjectionContainer>() ); } } 

Um ein Plug-In zu erstellen, müssen drei Klassen erstellt werden: die Klasse, die für die Plug-In-Konfiguration verantwortlich ist, der Plug-In-Anbieter und direkt das Plug-In selbst.

 public class DependencyInjectionPlugin { public IContainer Container { get; set; } public T Resolve<T>() { return Container.Resolve<T>(); } } 

 [PluginProviderType(typeof(DependencyInjectionPluginProvider))] public class DependencyInjectionPluginConfiguration : IPluginConfiguration { public void WriteBinary(IBinaryRawWriter writer) { // No-op } public int? PluginConfigurationClosureFactoryId { get; } = null; // No Java part } 

 public class DependencyInjectionPluginProvider : IPluginProvider<DependencyInjectionPluginConfiguration> { public string Name { get; } = "DependencyInjection"; public string Copyright { get; } = "MIT"; protected DependencyInjectionPlugin DependencyInjectionPlugin { get; set; } public T GetPlugin<T>() where T : class { return DependencyInjectionPlugin as T; } public void Start(IPluginContext<DependencyInjectionPluginConfiguration> context) { DependencyInjectionPlugin = new DependencyInjectionPlugin(); } public void Stop(bool cancel) { } public void OnIgniteStart() { } public void OnIgniteStop(bool cancel) { } } 

Großartig, es bleibt das Plugin in Apache Ignite.NET zu laden.

 public class IgniteInstaller : IWindsorInstaller { public void Install(IWindsorContainer container, IConfigurationStore store) { container.Register( Component .For<IIgnite>() .UsingFactoryMethod(() => Ignition.Start(new IgniteConfiguration { PluginConfigurations = new[] {new DependencyInjectionPluginConfiguration()} })) ); } } 

Wenn die Anwendung gestartet wird, initialisieren wir wie gewohnt den Abhängigkeitsinjektionscontainer, aber jetzt können wir ihn an das gerade geschriebene Plugin übergeben:

 var Done = new ManualResetEventSlim(false); // Build Windsor container using (var container = new WindsorContainer()) { // Install DI abstraction layer container.Install(new DependencyInjectionInstaller()); // Install cluster abstraction layer container.Install(new IgniteInstaller()); // Attach DI container to cluster plugin container .Resolve<IIgnite>() .GetPlugin<DependencyInjectionPlugin>("DependencyInjection") .Container = container.Resolve<IContainer>(); // Wait Done.Wait(); } 

Herzlichen Glückwunsch, wenn Sie bis zum Ende gelesen haben, können Sie jede Abhängigkeit von Ihrem Container innerhalb des Dienstes erhalten. Es sieht so aus:

 public class ClientConnectionService : IClientConnectionService, IService { private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); [InstanceResource] private IIgnite Ignite { get; set; } public void Init(IServiceContext context) { Logger.Debug("Initialized"); } public void Execute(IServiceContext context) { var plugin = Ignite.GetPlugin<DependencyInjectionPlugin>("DependencyInjection"); var whatever = plugin.Resolve<IWhatever>(); whatever.DoSomething(); } public void Cancel(IServiceContext context) { Logger.Debug("Canceled"); } } 

Source: https://habr.com/ru/post/de420479/


All Articles