我有这个(虚构的)桌面应用程序,它允许项目经理搜索空闲的开发人员并分配任务。该模型是:
interface IDeveloperFactory
{
IDeveloper CreateDeveloper(string name);
}
interface IDeveloper
{
void WriteCode();
void WriteUnitTest();
}
interface ITask
{
void Complete();
}
class Developer : IDeveloper
{
public Developer(string name) { ... }
public void WriteCode()
{
Console.WriteLine("Developer {0} is writing code... done", name);
}
public void WriteUnitTest()
{
Console.WriteLine("Developer {0} is writing unit test... done", name);
}
}
class WriteCodeTask : ITask
{
public Task(Lazy<IDeveloper> lazyDeveloper) { ... }
public void Complete()
{
var dev = lazyDeveloper.Value;
dev.WriteCode();
}
}
Developer
具有运行时依赖性,因此我将使用DeveloperFooFactory
(配置为类型化工厂)来获取IDeveloper
。虽然正在使用IDeveloper
,但我还需要ITask
使用开发人员实例,如果我可以让容器解决它们,我的工作会更容易:
var developerFactory = container.Resolve<IDeveloperFactory>();
var dev1 = developerFactory.CreateDeveloper("dev 1");
var task1 = container.Resolve<ITask>();
task1.Complete(); // uses dev1
var task2 = container.Resolve<ITask>();
task2.Complete(); // uses dev1
container.Release(dev1); // also releases task1 and task2
var dev2 = developerFactory.CreateDeveloper("dev 2");
var task3 = container.Resolve<ITask>();
task3.Complete(); // uses dev2
// task1, task2 and task3 are always different instances
问题:
dev1
之前释放dev2
(例如,在不同的线程上同时创建dev
)但我仍然需要容器来解析{{1}正确...我是否需要使用子容器,或者3.0中的新ITask
方法?我知道如果不是循环依赖,事情可能会更容易。然而,似乎这个模型,我的意思是真实的,这种方式更自然......
答案 0 :(得分:0)
最终想出来......看起来并不复杂,但我对温莎来说真的很新。
集装箱登记:
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component.For<IDeveloperFactory>().AsFactory(),
Component.For<IDeveloper>().ImplementedBy<Developer>().LifestyleScoped(),
Component.For<ITask>().ImplementedBy<WriteCodeTask>().LifestyleTransient(),
Component.For<Lazy<IDeveloper>>().LifestyleTransient() // i don't use 4.0 so this is my own implementation of Lazy<> which depends on a Func<> on ctor
);
测试代码:
var developerFactory = container.Resolve<IDeveloperFactory>();
using (container.BeginScope())
{
var developer = developerFactory.Create("John"); // this creates a new Developer and caches it in the current scope
var task1 = container.Resolve<ITask>();
var task2 = container.Resolve<ITask>();
Assert.Same(task1.Developer, task2.Developer);
Assert.Equal("John", task1.Developer.Name);
task1.Complete();
task2.Complete();
container.Release(task1);
container.Release(task2);
}
这证明可以使用相同的上下文开发人员实例解决这两个任务。
我的另一个要求就是在不同的线程上工作。这也没关系,因为如果using (container.BeginScope()) { ... }
代码在一个线程上运行,那么容器会为每个线程创建并缓存一个不同的开发人员实例。此外,我可以启动子线程来解决任务,并仍然可以获得正确的上下文开发人员实例。