您可能会考虑容器(非常智能的工厂)和建议(处理所有杂乱的细节)。
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.
您可能会在代码中看到这一点:
//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
}
提出拦截器类只发生一次。注册每个拦截器和服务类也只发生一次。设置容器(非常智能的工厂)当然很复杂。
但是,代码中必须使用服务对象的每个地方,并且必须将其嵌入到复杂而混乱的基础设施细节中,例如异常处理和日志记录,都变得非常干净和简单。只有一个CreateContainer
,但有数百个GottaGoDoSomething
,所以这很容易,但代价是有点复杂。
(注意:代码示例使用 Autofac 容器框架和 Castle 拦截器框架。我知道这是服务定位模式的示例,而不是依赖注入模式,但重点是说明拦截器并将它们注册到一个容器,不是为了说明依赖注入。)