Consider there is an Apache Ignite.NET cluster that provides service grid and you want to be able to execute distributed service that could access local dependency injector.
First, let’s create service itself.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
public class ClientConnectionService : IClientConnectionService, IService { private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); [InstanceResource] private IIgnite Ignite { get; set; } public void Listen(string hostname, int port, uint username, string password, ClientConnectionListenerOptions options = ClientConnectionListenerOptions.All) { Logger.Debug("Listen"); } public void Init(IServiceContext context) { Logger.Debug("Initialized"); } public void Execute(IServiceContext context) { Logger.Debug("Executed"); } public void Cancel(IServiceContext context) { Logger.Debug("Canceled"); } } |
As you know, Apache Ignite.NET automagically serializes services, sends them over the wire and deserializes on the node, where it will be executed. Thus, if we are using dependency injection container, Apache Ignite.NET simply does not know about it and won’t inject anything that it is not aware of. Luckily, we still can inject Apache Ignite.NET instance itself, by marking it with [InstanceResource] attribute.
Let’s introduce dependency injection container abstraction
1 2 3 4 |
public interface IContainer { T Resolve<T>(); } |
In order to introduce Apache Ignite.NET to dependency injection container abstraction, let’s create a simple plugin.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
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) { } } 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()} })) ); } } |
So far, so good, we are able to wire up our DI abstraction
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
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>() ); } } |
Finally, in application’s main method let’s complete the puzzle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
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(); } |
That’s it, now we are ready to access our DI abstraction in Apache Ignite.NET service:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public class ClientConnectionService : IClientConnectionService, IService { private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); [InstanceResource] private IIgnite Ignite { get; set; } public void Listen(string hostname, int port, uint username, string password, ClientConnectionListenerOptions options = ClientConnectionListenerOptions.All) { var plugin = Ignite.GetPlugin<DependencyInjectionPlugin>("DependencyInjection"); var whatever = plugin.Resolve<IWhatever>(); whatever.DoSomething(); } public void Init(IServiceContext context) { Logger.Debug("Initialized"); } public void Execute(IServiceContext context) { Logger.Debug("Executed"); } public void Cancel(IServiceContext context) { Logger.Debug("Canceled"); } } |
Enjoy!