[英]Windsor: how to configure the container when runtime dependencies are involved
我有这个(虚构的)桌面应用程序,它允许项目经理搜索闲置的开发人员并分配任务 。 该模型是:
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
,我还需要使用Developer实例的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
问题:
dev2
之前释放dev1
(例如,在不同线程上同时创建dev
),但是我仍然需要容器来正确解析ITask
……我是否需要为此使用子容器? 3.0中新的BeginScope
方法? 我知道,如果不是出于循环依赖,事情可能会容易一些。 但是,看起来这种模型(我真正的意思是这种模型)更自然了……
最终想通了...看起来并不复杂,但是我对Windsor真的很陌生。
集装箱注册:
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()) { ... }
代码,则容器将为每个线程创建并缓存一个不同的开发人员实例。 另外,我可以启动子线程来解决任务,并且仍将获得正确的上下文开发人员实例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.