我一直在努力通过在我的Web应用程序中实现IoC的细节,但是以利用Microsoft.Practices.ServiceLocation的方式。我特别使用Autofac和asp.net集成,但我想让自己开放给其他容器。沿着this question的路线,我很担心如何访问我的Web应用程序代码中的容器。Autofac,ASP.NET和Microsoft.Practices.ServiceLocation
我有一个'核心'库,主要定义要解决的接口。这个核心库也被我的网络应用和其他应用使用。非常方便定义通用接口。我认为这是访问IoC容器的好地方,而且我是用静态类来做的。诀窍是将容器注入静态类。
由于每个请求的容器可能不同,因此在Web环境中很棘手,而在非Web应用程序中,它可能会始终保持不变。起初我尝试用方法注入容器direclty,但很快就在下一个Web请求中失败!所以,我想出了这个:
public static class IoCContainer
{
public static void SetServiceLocator(Func<IServiceLocator> getLocator)
{
m_GetLocator = getLocator;
}
static private Func<IServiceLocator> m_GetLocator = null;
public static T GetInstance<T>(string typeName)
{
return m_GetLocator().GetInstance<T>(typeName);
}
}
现在,在我的global.asax.cs我这样做:
protected void Application_Start(object sender, EventArgs e)
{
var builder = new Autofac.Builder.ContainerBuilder();
... register stuff ...
var container = builder.Build();
_containerProvider = new Autofac.Integration.Web.ContainerProvider(container);
Xyz.Core.IoCContainer.SetServiceLocator(() =>
new AutofacContrib.CommonServiceLocator.AutofacServiceLocator
(_containerProvider.RequestContainer));
}
public IContainerProvider ContainerProvider
{
get { return _containerProvider; }
}
static IContainerProvider _containerProvider;
,并呼吁解决的依赖性看起来像
var someService = Xyz.Core.GetInstance<ISomeService>();
因此,而不是传递一个特定的容器,我传递一个知道如何获取容器的委托。对于非web应用程序,委托人可能会返回builder.Build()提供的内容。
我向专家提出的问题是,这是否有意义?我有一个简单的方法可以找到可以解决依赖关系的问题,而无需知道容器产品是什么或容器本身来自哪里。你怎么看?
这是非常酷的彼得,但我希望能够重用我的“核心”库在其他情况下,甚至没有基于网络。不过,我认为这是一个很好的答案,因为它有助于我避免太多的抽象。谢谢! – n8wrl 2009-10-08 13:51:34
我明白你的观点。尽管如此,如果你完全可以不使用服务定位器模式,而只使用依赖注入,你根本不需要解决这个问题:) – 2009-10-08 15:18:24