C# 多个具体类型的Castle Windsor IoC容器实例化

C# 多个具体类型的Castle Windsor IoC容器实例化,c#,inversion-of-control,castle-windsor,castle,C#,Inversion Of Control,Castle Windsor,Castle,我是国际奥委会和温莎城堡的新手 这个问题更多地与国际奥委会有关,但我只是选择城堡作为我选择的武器 我立即遇到了一个问题,即似乎无法从配置文件或单例构建容器 对我来说唯一可行的方法是使用一个生成器函数,它每次都会构造整个容器,然后让我指定类型,看看这个示例: 我有一个看法: public interface IView { } 此视图有两个具体实现: public class ConcreteViewA : IView { } public class ConcreteViewB : IVie

我是国际奥委会和温莎城堡的新手

这个问题更多地与国际奥委会有关,但我只是选择城堡作为我选择的武器

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

对我来说唯一可行的方法是使用一个生成器函数,它每次都会构造整个容器,然后让我指定类型,看看这个示例:

我有一个看法:

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;
    }
我有两个根入口点:

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使用什么。
如果容器重建大量类型等的成本很高,我该如何设计呢?

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

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

据我所知,您需要控制器类的两个不同实例,每个实例都使用不同的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时还要记住的几件事

只构建一次容器一次又一次地构建容器是浪费时间和资源的

非常确定哪些依赖项要注入,哪些不要注入。过度使用DI会导致容器膨胀,这是维护的噩梦

了解组件的生命周期-单线程、瞬态、每线程等。特别是Castle的默认生活方式是单线程,这可能会在多线程场景中产生不一致的行为


据我所知,您需要控制器类的两个不同实例,每个实例都使用不同的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时还要记住的几件事

只构建一次容器一次又一次地构建容器是浪费时间和资源的

非常确定哪些依赖项要注入,哪些不要注入。过度使用DI会导致容器膨胀,这是维护的噩梦

了解组件的生命周期-单线程、瞬态、每线程等。特别是Castle的默认生活方式是单线程,这可能会在多线程场景中产生不一致的行为


这是否适用于MVC应用程序?如果是这样,IView的实例做什么?我问,因为在ASP.Net应用程序中,选择控制器上的操作应返回哪个视图是由框架处理的。不,这是winforms的自定义实现。页面加载事件将创建控制器/演示器,该控制器/演示器接收当前实例的视图,因此无法创建该视图。我不知道该示例有多简化,但通常控制器与特定视图类型相关联。您遇到的问题可能是设计问题,而不是框架使用问题。我同意您的看法,您可以看到,我的控制器确实依赖于IView类型,但为什么我的控制器必须关心IView的具体实现是什么,问题只是告诉每个上下文的容器具体视图是什么。所有其他类型保持不变。为了获得帮助,我确实简化了这个示例,但是想象一下控制器接受了一些依赖项,其中大多数依赖项保持不变,除了可以更改的具体视图外,ioc可以轻松地处理它们。这对于MVC应用程序是否适用?如果是这样,IView的实例做什么?我问,因为在ASP.Net应用程序中,选择控制器上的操作应返回哪个视图是由框架处理的。不,这是winforms的自定义实现。页面加载事件将创建控制器/演示器,该控制器/演示器接收当前实例的视图,因此无法创建该视图。我不知道该示例有多简化,但通常控制器与特定视图类型相关联。您遇到的问题可能是设计问题,而不是框架使用问题。我同意您的看法,正如您所看到的,我的控制器确实依赖于IView类型,但为什么我的控制器必须关心IView的具体实现是什么,问题只是告诉每个上下文的容器 具体的观点是什么。所有其他类型保持不变。为了得到帮助,我确实简化了这个示例,但是想象一下控制器接受了一些依赖项,其中大多数依赖项保持不变,并且很容易由ioc处理,但具体视图可以更改。