【问题标题】:Castle Windsor IoC Container Instantiation for multiple concrete types用于多种具体类型的 Castle Windsor IoC 容器实例化
【发布时间】:2011-10-07 16:22:39
【问题描述】:

我是 IoC 和温莎城堡的新手。

这个问题与 IoC 更相关,但我只是选择了城堡作为我选择的武器。

我立即遇到了一个问题,似乎不可能从配置文件或单例构造容器。

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

我有一个看法:

public interface IView
{
}

这个视图有2个具体的实现:

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 个(根)入口点:

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 的重建成本很高(很多类型等),我该如何设计呢?

【问题讨论】:

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

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


【解决方案1】:

据我了解,您需要两个不同的 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. 了解组件的生命周期(单例、瞬态、每个线程等)。特别是对于 Castle,默认的生活方式是单例的,这可能会在多线程场景中产生不一致的行为。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多