如何使用简单的注射器上改变依赖登记在运行时? [英] How to change dependency registration at run time using simple injector?
问题描述
我用href="http://simpleinjector.$c$cplex.com" rel="nofollow">简单的注射器 IoC框架的 A 和 B
,接口我
。实施 A
被记录在应用程序启动,但根据一些标志,它可以在运行时改变,我想切换的实现。我们现在正在做的这个 OnActionExecuting
事件我们 BaseController
,其中我们所有的控制器,从继承。这里是什么,我试图做样品code。
I'm using the Simple Injector IoC framework, and I would like to be able to change the dependency registration at run time. For example, I have two implementations, A
and B
, of interface I
. Implementation A
is registered at app start, but depending on some flag which can change during runtime, I would like to switch the implementation. We are currently doing this the OnActionExecuting
event of our BaseController
, which all of our controllers inherit from. Here is the sample code of what I am trying to do.
protected override void OnActionExecuting(
ActionExecutingContext filterContext)
{
if (IsRuntimeFlag)
{
// check current implementation type and
// change implementation to A
}
else
{
// check current implementation type and
// change implementation to B
}
base.OnActionExecuting(filterContext);
}
在此先感谢您的帮助。
Thanks in advance for your help.
推荐答案
您可以注册一个工厂委托是这样的:
You can either register a factory delegate like this:
container.Register<I>(() =>
{
if (IsRuntimeFlag)
{
return container.GetInstance<A>();
}
else
{
return container.GetInstance<B>();
}
});
然而,当这种 IsRuntimeFlag
是一个配置值(这样可以在应用程序的生命周期内没有改变),最好是进行如下注册:
However, when this IsRuntimeFlag
is a configuration value (thus cannot change during the lifetime of the application), it is better to register it as follows:
if (IsRuntimeFlag)
{
container.Register<I, A>();
}
else
{
container.Register<I, B>();
}
这使注册更具有确定性,它允许您验证容器有更多的确定性。
This makes the registration more deterministic, which allows you to validate the container with more certainty.
也可以创建一个复合与调度到正确的实例涉及:
Or you can create a composite that deals with dispatching to the right instance:
public class RuntimeFlagIComposite : I
{
private A a;
private B b;
public RuntimeFlagIComposite(A a, B b)
{
this.a = a;
this.b = b;
}
void I.Method()
{
var instance = IsRuntimeFlag ? this.a : this.b;
instance.Method();
}
}
由于复合材料直接取决于 A
和 B
,你可以简单地注册,如下所示:
Because the composite directly depends on A
and B
, you can simply register it as follows:
container.Register<I, RuntimeFlagIComposite>();
在 A
或 B
有不同的寿命暂时性的(每个请求一个新的实例),你应该还注册。例如:
When A
or B
have a different lifetime than transient (a new instance for each request), you should also register them. For instance:
container.RegisterSingle<A>();
container.RegisterPerWebRequest<B>();
您也可以让你的组合取决于我
抽象本身,而不是具体的 A
和 B
实现:
You can also let your composite depend on the I
abstraction itself instead of the concrete A
and B
implementations:
public class RuntimeFlagIComposite : I
{
private I a;
private I b;
public RuntimeFlagIComposite(I a, I b)
{
this.a = a;
this.b = b;
}
}
根据我
抽象使得这个类更灵活,更容易测试。但它确实意味着,你需要注册它一点点不同:
Depending on the I
abstraction makes this class more flexible and more testable. It does mean however, that you need to register it a little bit different:
container.Register<I>(() => new RuntimeFlagIComposite(
container.GetInstance<A>(),
container.GetInstance<B>())
);
通常注册一个简单的代表(作为首次登记显示)往往是不够的,但创建一个单独的类型可以有利于在某些情况下。
Often registering a simple delegate (as the first registration showed) is often enough, but creating a separate type can be beneficial in some situations.
其实,这是一个可以可以适用于(几乎)所有的DI框架一种普遍现象。
In fact, this is a general pattern that can can apply to (almost) every DI framework.
这篇关于如何使用简单的注射器上改变依赖登记在运行时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!