wcf dependency-injection castle-windsor

wcf - Castle.Windsor: resolución opcional del componente de una fábrica tipada



dependency-injection castle-windsor (1)

Steven señala dos formas de explorar para llegar a una solución:

  • No verifique nulo, más bien use un Patrón de Objeto Nulo
  • Envuelva el IHandler<T> con un decorador e inyecte el IInjector en el decorador

La segunda opción no era deseable ya que habría cargado a los controladores con una responsabilidad que no tenían que conocer. Idealmente, debería mover este comportamiento de inyección a su propio interceptor independiente y dejarlo vivir completamente allí sin ningún otro código que lo sepa. Puedo hacer eso más tarde.

El primer punto, sin embargo, es el camino a seguir. El Patrón de objeto nulo disminuye la complejidad de mi método y lo deja mucho más claro que con un cheque nulo. Todo lo que tengo que hacer es crear una clase NopInjector y declararla como el valor predeterminado para la fábrica.

No intente crear un inyector en función de un objeto base:

public class NopInjector : IInjector<object> { public void InjectStuff(object target, string stuff) { } }

Más bien, cree un inyector genérico y regístrelo como un componente genérico abierto

public class NopInjector<T> : IInjector<T> { public void InjectStuff(T target, string stuff) { } } // registration _container.Register( Component.For(typeof(IInjector<>)) .ImplementedBy(typeof(NopInjector<>)) .IsDefault()); _container.Register( Classes .FromAssemblyInThisApplication() .BasedOn(typeof(IInjector<>)) .WithService.AllInterfaces());

Ahora si Castle.Windsor puede resolver un IInjector<Command> específico IInjector<Command> lo hará, de lo contrario devolverá el NopInjector . No más cheque nulo:

private static void DoActualWork<T>(T command) { injectorFactory.GetInjector<T>().InjectThings(command, ""); // calling handlers... }

Tengo una configuración de servicio WCF con Castle.Windsor; los mensajes llegan a un despachador que los envía al componente correcto (básicamente un IHandler<Message> con un mensaje que es una consulta).

Sin embargo, en algunos casos, hay uno adicional antes de que el controlador pueda actuar; el mensaje debe completarse con datos provenientes de otro lugar. Lo que quiero es verificar si existe un inyector para el tipo de mi mensaje y, si existe uno, ejecútelo.

IInjector<Message> Injector = InjectorFactory.RetrieveInjector<Message>(); if (Injector != null) { Logger.InfoFormat("IInjector<{0}> OK", input.GetType().Name); Injector.InjectCode(input, "Data coming from somewhere else"); }

El razonamiento detrás de esto es que en algún momento futuro alguien puede crear un complemento con un IInjector<Message> y quiero IInjector<Message> en el futuro; pero por el momento no existe.

¿Es posible hacer que una fábrica de tipeo devuelva nulo cuando no se encuentra un componente en lugar de lanzar una ComponentNotFoundException ?

EDITAR

Tal como lo discutí con @Steven, responderé mi propia pregunta para recopilar lo que me condujo a la solución y la resolución que encontré. Primero, replanteemos el problema

Tengo un servicio WCF básicamente siguiendo la estructura descrita por Krzysztof Koźmic en este artículo

Sin embargo, antes de llamar a los controladores, quería tener una operación opcional donde el mensaje entrante se modificaría si fuera necesario.

private static void DoActualWork<T>(T command) { IInjector<T> Injector = injectorFactory.GetInjector<T>(); if (Injector != null) { Injector.InjectThings(command, ""); } var handlers = factory.GetHandlersForCommand(command); foreach (var handler in handlers) { handler.Execute(); } }

Estaba teniendo un problema con injectorFactory; cuando le pedí que encontrara un componente inexistente arrojaría una ComponentNotFoundException . Lo que me hubiera gustado es que la fábrica reconozca que no hay componentes y simplemente devuelve un valor nulo.