Inyección de dependencias en el servicio Apache Ignite.NET

Mientras desarrollaba varias aplicaciones que usan la popular biblioteca de Castle Windsor para inyectar dependencias y Apache Ignite.NET como la "clave" que abre la puerta a la computación en la nube, encontré un pequeño inconveniente: no tenía forma de inyectar la dependencia en el servicio lanzado a través del llamado Service Grid.

La razón por la que esto sucede es bastante común. Apache Ignite.NET serializa el servicio, lo envía a uno de los servidores disponibles, donde se deserializa y se inicia. Dado que este proceso de ninguna manera tiene idea sobre Castle Windsor, obtenemos lo que obtenemos.

Para resolver este problema, necesitamos crear un complemento para Apache Ignite.NET, que recibirá un contenedor responsable de implementar las dependencias y brindará al servicio la oportunidad de acceder a él para recibir un objeto.

En primer lugar, introduciremos un nivel adicional de abstracción para el contenedor, que proporciona inyección de dependencia, para que en el futuro podamos cambiar fácilmente su implementación a otra:

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>() ); } } 

Para crear un complemento, necesitamos crear 3 clases: la clase responsable de la configuración del complemento, el proveedor del complemento y, directamente, el complemento en sí.

 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) { } } 

Genial, queda cargar el complemento en Apache Ignite.NET.

 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()} })) ); } } 

Cuando se inicia la aplicación, nosotros, como de costumbre, inicializamos el contenedor de inyección de dependencia, pero ahora estamos listos para pasarlo al complemento que acabamos de escribir:

 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(); } 

Felicitaciones, si lees hasta el final, puedes obtener cualquier dependencia de tu contenedor dentro del servicio. Se ve así:

 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/es420479/


All Articles