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

And*_*dre 1 c# castle-windsor castle inversion-of-control

我是IoC和Castle Windsor的新手.

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

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

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

我有一个观点:

public interface IView
{
}
Run Code Online (Sandbox Code Playgroud)

此视图有两个具体实现:

public class ConcreteViewA : IView
{
}

public class ConcreteViewB : IView
{
}
Run Code Online (Sandbox Code Playgroud)

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

public class Controller
{
    public Controller(IView view) { }
    public void Load() { }
}
Run Code Online (Sandbox Code Playgroud)

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

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

我有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();
    }
Run Code Online (Sandbox Code Playgroud)

正如你可以看到我每次都要重建容器,因为我需要告诉它使用什么IVIEW每个我在上下文的.如果什么容器是昂贵的重建(批号类型等),我怎么能设计这个?

utt*_*ini 6

根据我的理解,您需要两个不同的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;
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以根据需要询问任何控制器.

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

void RootMethod2()
{
   var controller = container.Resolve<Controller>("ControllerWithViewB");
   controller.Load();
}
Run Code Online (Sandbox Code Playgroud)

使用DI时要记住的一些事项

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

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

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