温莎城堡 IoC 容器实例化多种具体类型
我是国际奥委会和温莎城堡的新手。
这个问题与 IoC 更相关,但我只是选择 Castle 作为我的首选武器。
我立即遇到了一个问题,似乎不可能从配置文件或单例构造容器。
似乎对我有用的唯一方法是使用 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 的内容。 如果容器的重建成本很高(很多类型等)怎么办,我该如何设计?
I am new to IoC and Castle Windsor.
The question is more related to IoC, but i just chose Castle as my weapon of choice.
I immediately ran into a problem that it seems impossible to construct the container from a config file or from a singleton.
The only way seeming to work for me is to use a Builder function that will construct the whole container each time and then let me specify the types, look at this example:
I have a view:
public interface IView
{
}
There are 2 concrete implementations of this view:
public class ConcreteViewA : IView
{
}
public class ConcreteViewB : IView
{
}
I have a controller that operates on the view:
public class Controller
{
public Controller(IView view) { }
public void Load() { }
}
I create a function that constructs my IoC container and register the common types, the only type i can register is my controller, as this is all that stays the same:
WindsorContainer BuildContainer()
{
var container = new WindsorContainer();
container.Register(Component.For<Controller>().ImplementedBy<Controller>());
return container;
}
I have 2 (Root) entry points:
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();
}
As you can see I have to rebuild the container each time as i need to tell it what to use for IView for each of the context i am in.
What if the Container is expensive to rebuild (Lots of types etc), how can I design this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
据我了解,您需要 Controller 类的两个不同实例(每个实例都使用不同的 IView 类型构造)。实现这一点的最简单方法是注册两个具有不同名称和不同依赖项的组件。
然后,您可以在需要时请求任何控制器。
使用 DI 时需要记住的一些事情
仅构建容器一次(一次又一次构建是浪费时间和资源)。
非常确定要注入哪些依赖项,不要注入哪些依赖项。过度使用 DI 可能会导致容器臃肿,这是维护的噩梦。
了解组件的生命周期(单例、瞬态、每线程等)。特别是对于 Castle,默认生活方式是单例,这可能会在多线程场景中产生不一致的行为。
From what I understand, you need two different instances of the Controller class (each one constructed with a different IView type). The easiest way to achieve this is to register two components with different names and different dependencies.
You can then ask for any controller as and when required.
A few more things to keep in mind when using DI
Build your container only once (Building it again and again is a waste of time and resources).
Be very sure which dependencies to inject and which not to. Overusing DI for everything can result in a bloated container which is a maintenance nightmare.
Be informed about the life cycle of your components (Singleton, Transient, per thread etc). Especially with Castle the default lifestyle is singleton which might create inconsistent behavior in a multi-threaded scenario.
您可以考虑使用处理程序选择器。这将允许您根据您选择的代码动态选择要解析的视图。请参阅此处。
You could look at using a handler selector. This would allow you to dynamically choose which view to resolve based on whatever code you choose. See here.