Castle Windsor IoC容器实例,适用于多种混凝土类型

时间:2011-10-07 16:22:40

标签: c# inversion-of-control castle-windsor castle

我是IoC和Castle Windsor的新手。

问题与IoC有关,但我选择Castle作为我的首选武器。

我立即遇到一个问题,似乎无法从配置文件或单例构建容器。

似乎对我有用的唯一方法是使用Builder函数,每次都构造整个容器,然后让我指定类型,看看这个例子:

我有一个观点:

public interface IView
{
}

此视图有两个具体实现:

public class ConcreteViewA : IView
{
}

public class ConcreteViewB : IView
{
}

我有一个对视图进行操作的控制器:

public class Controller
{
    public Controller(IView view) { }
    public void Load() { }
}

我创建了一个构造我的IoC容器并注册常见类型的函数,我可以注册的唯一类型是我的控制器,因为这一切都保持不变:

WindsorContainer BuildContainer()
    {
        var container = new WindsorContainer();
        container.Register(Component.For<Controller>().ImplementedBy<Controller>());
        return container;
    }

我有2个(Root)入口点:

void RootMethod1()
    {
        var container = BuildContainer();
        container.Register(Component.For<IView>().ImplementedBy<ConcreteViewA>());
        var controller = container.Resolve<Controller>();
        controller.Load();
    }

    void RootMethod2()
    {
        var container = BuildContainer();
        container.Register(Component.For<IView>().ImplementedBy<ConcreteViewB>());
        var controller = container.Resolve<Controller>();
        controller.Load();
    }

正如你所看到的,我每次都需要重建容器,因为我需要告诉它我在每个上下文中使用什么来进行IView。 如果Container的重建成本很高(很多类型等),我该如何设计呢?

2 个答案:

答案 0 :(得分:5)

据我所知,您需要两个不同的Controller类实例(每个实例都使用不同的IView类型构建)。实现此目的的最简单方法是注册具有不同名称和不同依赖关系的两个组件。

WindsorContainer BuildContainer()
{
    var container = new WindsorContainer();

        container.Register(Component.For<Controller>().Named("ControllerWithViewA")
                                                      .ImplementedBy<Controller>()
                                                      .DependsOn(Property.ForKey(typeof(IView))
                                                      .Is(typeof(ConcreteViewA)));
        container.Register(Component.For<Controller>().Named("ControllerWithViewB")
                                                     .ImplementedBy<Controller>()
                                                     .DependsOn(Property.ForKey(typeof(IView))
                                                     .Is(typeof(ConcreteViewB)));
    return container;
}

然后,您可以在需要时询问任何控制器。

void RootMethod1()
{
    var container = BuildContainer();
    var controller = container.Resolve<Controller>("ControllerWithViewA");
    controller.Load();
}

void RootMethod2()
{
   var controller = container.Resolve<Controller>("ControllerWithViewB");
   controller.Load();
}

使用DI时需要注意的一些事项

  1. 只构建一次容器(一次又一次地构建它是浪费时间和资源)。

  2. 要非常确定要注入哪些依赖项,哪些不依赖。对所有东西过度使用DI会导致膨胀的容器,这是一个维护噩梦。

  3. 了解组件的生命周期(Singleton,Transient,per thread等)。特别是使用Castle时,默认生活方式是singleton,它可能会在多线程场景中产生不一致的行为。

答案 1 :(得分:1)

您可以查看使用处理程序选择器。这将允许您根据您选择的代码动态选择要解析的视图。请参阅here