一般而言,大多數依賴項可以在創建時注入到您的類中。但是,在這種特殊情況下,您需要一個必須在使用時按需創建的組件。在這種情況下,完全刪除對IoC容器的依賴是非常困難的。我的方法一直是創建一個在創建時注入到類中的工廠,這反過來又封裝了所有直接的IoC用法。這樣就可以模擬來測試你的工廠,而不是IoC容器本身......這往往是一個容易得多:
// In Presentation.csproj
class PresentationController
{
public PresentationController(IDataContextFactory dataContextFactory, IRepositoryFactory repositoryFactory)
{
#region .NET 4 Contract
Contract.Requires(dataContextFactory != null);
Contract.Requires(repositoryFactory != null);
#endregion
_dataContextFactory = dataContextFactory;
_repositoryFactory = repositoryFactory;
}
private readonly IDataContextFactory _dataContextFactory;
private readonly IRepositoryFactory _repositoryFactory;
public void Action()
{
using (IDataContext dc = _dataContextFactory.CreateInstance())
{
var repo = _repositoryFactory.CreateUserRepository();
// do stuff with repo...
}
}
}
// In Factories.API.csproj
interface IDataContextFactory
{
IDataContext CreateInstance();
}
interface IRepositoryFactory
{
IUserRepository CreateUserRepository();
IAddressRepository CreateAddressRepository();
// etc.
}
// In Factories.Impl.csproj
class DataContextFactory: IDataContextFactory
{
public IDataContext CreateInstance()
{
var context = IoC.Resolve<IDataContext>();
// Do any common setup or initialization that may be required on 'context'
return context;
}
}
class RepositoryFactory: IRepositoryFactory
{
public IUserRepository CreateUserRepository()
{
var repo = IoC.Resolve<IUserRepository>();
// Do any common setup or initialization that may be required on 'repo'
return repo;
}
public IAddressRepository CreateAddressRepository()
{
var repo = IoC.Resolve<IAddressRepository>();
// Do any common setup or initialization that may be required on 'repo'
return repo;
}
// etc.
}
這種方法的好處是,雖然你不能完全消除IOC依賴本身,您可以將其封裝在單一類型的對象(工廠)中,將大部分代碼與IoC容器解耦。例如,從一個IoC容器切換到另一個(即Windsor到Ninject),這可以提高您的代碼敏捷性。
應該指出,這樣做的一個有趣的結果是,你的工廠通常是通過它們使用的相同的IoC框架注入到他們的家屬。例如,如果您正在使用Castle Windsor,則可以創建配置,告訴IoC容器在創建時將兩個工廠注入到業務組件中。業務組件本身也可能有一個工廠......或者它可以簡單地由相同的IoC框架注入到一個更高級別的組件中,等等。
感謝您的回答。唯一的問題是我使用的IoC應該有一個相對於'using'語句的範圍。然後,如果我解析說'IDataContext'它將解決該特定範圍的*單個實例*。我不希望我的控制器等意識到IoC容器,但是真的有辦法解決這個問題嗎? – TheCloudlessSky 2010-07-01 10:54:44
我想知道如果一個控制器應該能夠調用IoC.Resolve?如果不是,誰應該打這個電話? –
TheCloudlessSky
2010-07-01 12:01:07
你能解釋一下這個範圍嗎?您使用的是什麼IoC容器?一般來說,以任何方式將任何代碼耦合到容器框架是一種消極的耦合方式......您應該不惜一切代價避免這種情況。根據我的經驗,範圍(或上下文)很少(如果有的話)需要IoC容器工作。如果它以這種方式工作,我會找到一個替代容器,或者找到一種方法將這種上下文提供給解決您的對象的工廠,並儘可能保持您的IoC框架解耦。 – jrista 2010-07-01 16:24:38