我一直在努力通過在我的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