Puede pensar en contenedores (fábricas muy inteligentes) y consejos (para manejar todos los detalles desordenados).
Dear Mr. Container Sir,
Whenever I request from you an instance object of the interface ISomething,
please construct for me an instance of the concrete class SomethingImpl;
in addition, please see to it (however you do it) that, whenever I call a
method on this instance, it is wrapped within a complicated and messy try-
catch-finally which logs exceptions and mark calls as completed. That way,
all I have to do is write the business logic that goes into the SomethingImpl
and I don't have to worry about all the messy infrastuctural details.
Sincerely,
Mr. Agile.
Es posible que vea esto, en clave, como:
//a class that knows how to take care of the messy infrastructure details
public class MyMessyInterceptor : IInterceptor {
public void Intercept(IInvocation invocation) {
//handle the messy details of continuing with the method-invocation,
//but within a try-catch-finally that includes exception handling and
//call logging.
}
}
//a function that will configure a container (very smart factory)
public IContainer CreateContainer() {
var builder = new ContainerBuilder();
//tell the container-builder about the interceptor
builder
.Register(c => new MyMessyInterceptor())
.Named("keep-my-code-clean")
;
//tell the container what to do when you ask it for a ISomething
builder
.Register<SomethingImpl>()
.As<ISomething>()
.InterceptedBy("keep-my-code-clean")
;
return builder.BuildContainer();
}
//some function out there in your code somewhere that needs to make a
//service call; there's hundreds of functions out there just like this
//in your code, and they all just got much simpler
public object GottaGoDoSomething() {
//find the container
var container = GetTheSingletonContainerObject();
//ask for an instance of ISomething - it knows to provide a
//SomethingImpl wrapped in an interceptor that takes care of all
//the logging and exception handling
var something = container.resolve<ISomething>();
//call the big method
return something.DoSomething();
//magically (not really), the exception handling and logging are
//already taken care of
}
El subir con la clase de interceptor sucede sólo una vez. El registro de cada interceptor y clase de servicio también ocurre solo una vez.Configurar el contenedor (fábrica muy inteligente) es ciertamente complicado.
Sin embargo, cada lugar en su código que tiene que usar el objeto de servicio, y tiene que incorporar ese uso dentro de detalles de infraestructura complicados y desordenados como el manejo y registro de excepciones, acaba de ser muy limpio y sin complicaciones. Solo hay un CreateContainer
, pero hay cientos de GottaGoDoSomething
s, así que es mucho más fácil a costa de un poco complicado.
(Notas: El ejemplo del código utiliza el marco del contenedor Autofac y el marco del interceptor Castle. Soy consciente de que este es un ejemplo del patrón de ubicación del servicio, no el patrón de inyección de dependencia, pero el punto era ilustrar interceptores y registrarlos con un contenedor, no para ilustrar la inyección de dependencia.)
Ya tiene el formato ideal. –