Причина по которой это происходит довольна банальна. Apache Ignite.NET сериализует сервис, отправляет его на один из доступных серверов, где он десериализуется и запускается. Так как этот процесс никаким образом не имеет понятия о Castle Windsor, мы получаем то, что получаем.
Для решения этой проблемы нам необходимо создать плагин для Apache Ignite.NET, который получит контейнер, отвечающий за внедрение зависимостей и предоставить возможность сервису обратиться к нему, для получения того или иного объекта.
Первым делом внедрим дополнительный уровень абстракции для контейнера, обеспечивающего внедрения зависимостей, для того чтобы в будущем мы могли легко сменить его имплементацию на другую:
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>() ); } }
Для создания плагина нам необходимо создать 3 класса: класс, отвечающий за конфигурацию плагина, провайдер плагина и, непосредственно, сам плагин.
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) { } }
Отлично, осталось загрузить плагин в 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()} })) ); } }
При старте приложения мы, как обычно, инициализируем контейнер внедрения зависимостей, однако теперь мы готовы передать его плагину, который только что написали:
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(); }
Поздравляю, если вы дочитали до конца, то вы сможете получить любую зависимость из вашего контейнера внутри сервиса. Выглядит это так:
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"); } }
ссылка на оригинал статьи https://habr.com/post/420479/
Добавить комментарий