En développant diverses applications qui utilisent la bibliothèque populaire de
Castle Windsor pour
injecter des dépendances et
Apache Ignite.NET comme la «clé» qui ouvre la porte au cloud computing, j'ai rencontré un léger inconvénient: je n'avais aucun moyen d'injecter la dépendance dans le service lancé à travers la soi-disant grille de service.
La raison pour laquelle cela se produit est assez courante. Apache Ignite.NET sérialise le service, l'envoie à l'un des serveurs disponibles, où il est désérialisé et lancé. Puisque ce processus n'a aucun indice sur Castle Windsor, nous obtenons ce que nous obtenons.
Pour résoudre ce problème, nous devons créer un plug-in pour Apache Ignite.NET, qui recevra un conteneur responsable de l'implémentation des dépendances et fournira au service la possibilité d'y accéder afin de recevoir un objet.
Tout d'abord, nous allons introduire un niveau d'abstraction supplémentaire pour le conteneur, qui fournit une injection de dépendance, afin qu'à l'avenir nous puissions facilement changer son implémentation en un autre:
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>() ); } }
Pour créer un plug-in, nous devons créer 3 classes: la classe responsable de la configuration du plug-in, le fournisseur du plug-in et, directement, le plug-in lui-même.
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) {
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) { } }
Génial, il reste à charger le plugin dans 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()} })) ); } }
Lorsque l'application démarre, nous, comme d'habitude, initialisons le conteneur d'injection de dépendances, mais maintenant nous sommes prêts à le passer au plugin que nous venons d'écrire:
var Done = new ManualResetEventSlim(false);
Félicitations, si vous lisez jusqu'à la fin, vous pouvez obtenir n'importe quelle dépendance de votre conteneur à l'intérieur du service. Cela ressemble à ceci:
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"); } }