繁体   English   中英

温莎:如何配置容器时,运行时依赖参与

[英]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

问题:

  1. 如何配置容器以实现此目的? (我打算使用3.0版)
  2. 理想情况下,我不会在创建dev2之前释放dev1 (例如,在不同线程上同时创建dev ),但是我仍然需要容器来正确解析ITask ……我是否需要为此使用子容器? 3.0中新的BeginScope方法?
  3. 开发人员也可以一次在不同线程上处理多个任务。 因此,每当我需要一项任务时,我只会要求容器将其解析并使用“上下文开发人员”实例...但是如何?

我知道,如果不是出于循环依赖,事情可能会容易一些。 但是,看起来这种模型(我真正的意思是这种模型)更自然了……

最终想通了...看起来并不复杂,但是我对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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM