关于此主题的讨论很多,但是每个人似乎都错过了一个显而易见的答案。我需要帮助来审核这个“显而易见的” IOC容器解决方案。各种对话均假定在运行时选择策略并使用IOC容器。我将继续这些假设。
我还想添加一个假设,即不是必须选择的单个策略。相反,我可能需要检索一个对象图,该对象图在整个图的节点中都有几种策略。
我将首先快速概述这两个通常提出的解决方案,然后介绍我想看到IOC容器支持的“明显”替代方案。尽管我的问题并非特定于Unity,但我将使用Unity作为示例语法。
命名绑定(bind)
这种方法要求每个新策略都必须手动添加一个绑定(bind):
Container.RegisterType<IDataAccess, DefaultAccessor>();
Container.RegisterType<IDataAccess, AlphaAccessor>("Alpha");
Container.RegisterType<IDataAccess, BetaAccessor>("Beta");
...然后明确要求正确的策略:
var strategy = Container.Resolve<IDataAccess>("Alpha");
抽象工厂
为了说明这种方法,请假定以下类:
public class DataAccessFactory{
public IDataAccess Create(string strategy){
return //insert appropriate creation logic here.
}
public IDataAccess Create(){
return //Choose strategy through ambient context, such as thread-local-storage.
}
}
public class Consumer
{
public Consumer(DataAccessFactory datafactory)
{
//variation #1. Not sufficient to meet requirements.
var myDataStrategy = datafactory.Create("Alpha");
//variation #2. This is sufficient for requirements.
var myDataStrategy = datafactory.Create();
}
}
然后,IOC容器具有以下绑定(bind):
Container.RegisterType<DataAccessFactory>();
类型切换/动态绑定(bind)
这是我要使用的方法,而不是上面的两种方法。它涉及在IOC容器绑定(bind)中提供一个委托(delegate)。几乎所有的IOC容器都已经具有此功能,但是此特定方法具有重要的细微差别。
语法如下所示:
Container.RegisterType(typeof(IDataAccess),
new InjectionStrategy((c) =>
{
//Access ambient context (perhaps thread-local-storage) to determine
//the type of the strategy...
Type selectedStrategy = ...;
return selectedStrategy;
})
);
请注意,
InjectionStrategy
没有返回IDataAccess
的实例。相反,它返回实现IDataAccess
的类型描述。然后,IOC容器将执行该类型的常规创建和“构建”,其中可能包括选择其他策略。这与标准的类型到委托(delegate)绑定(bind)形成对比,在Unity的情况下,绑定(bind)是这样编码的:
Container.RegisterType(typeof(IDataAccess),
new InjectionFactory((c) =>
{
//Access ambient context (perhaps thread-local-storage) to determine
//the type of the strategy...
IDataAccess instanceOfSelectedStrategy = ...;
return instanceOfSelectedStrategy;
})
);
上面的代码实际上很接近满足整体需求,但是绝对没有达到假设的Unity
InjectionStrategy
。关注第一个样本(使用了假设的Unity
InjectionStrategy
):Type
不可用,所以这意味着首次返回该类型时性能可能会受到影响。换句话说,容器必须当场反射(reflect)类型以发现其具有的构造函数,以便知道如何注入(inject)它。该类型的所有后续出现都应该很快,因为容器可以缓存从第一次发现的结果。这几乎不是一个“骗局”,值得一提,但我正在尝试进行全面披露。 是否存在可以以这种方式运行的现有IOC容器?任何人都有实现此效果的Unity自定义注入(inject)类?
最佳答案
据我所知,这个问题与几种候选策略之一的运行时选择或映射有关。
没有理由依赖DI容器来执行此操作,因为至少有三种方法可以通过与容器无关的方式来执行此操作:
我的个人偏好是“部分类型名称角色提示”。
关于c# - 依赖注入(inject)和策略模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22701412/