Хабрахабр

[Из песочницы] Внедрение зависимостей в сервис Apache Ignite.NET

Разрабатывая различные приложения, использующие популярную библиотеку Castle Windsor для внедрения зависимостей и Apache Ignite.NET в качестве «ключика», который открывает дверь в «облачные» вычисления, я столкнулся с небольшим неудобством: у меня не было никакой возможности внедрить зависимость в сервис, запускаемый через так называемый Service Grid.

Apache Ignite. Причина по которой это происходит довольна банальна. Так как этот процесс никаким образом не имеет понятия о Castle Windsor, мы получаем то, что получаем. NET сериализует сервис, отправляет его на один из доступных серверов, где он десериализуется и запускается.

NET, который получит контейнер, отвечающий за внедрение зависимостей и предоставить возможность сервису обратиться к нему, для получения того или иного объекта. Для решения этой проблемы нам необходимо создать плагин для Apache Ignite.

Первым делом внедрим дополнительный уровень абстракции для контейнера, обеспечивающего внедрения зависимостей, для того чтобы в будущем мы могли легко сменить его имплементацию на другую:

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

public class DependencyInjectionContainer : IContainer 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"); }
}

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть