我可以将构造函数参数传递给Unity的Resolve()方法吗?

Not*_*Dan 87 .net c# dependency-injection unity-container constructor-injection

我使用Microsoft的Unity进行依赖注入,我想做这样的事情:

IDataContext context = _unityContainer.Resolve<IDataContext>();
var repositoryA = _unityContainer.Resolve<IRepositoryA>(context); //Same instance of context
var repositoryB = _unityContainer.Resolve<IRepositoryB>(context); //Same instance of context

IDataContext context2 = _unityContainer.Resolve<IDataContext>(); //New instance
var repositoryA2 = _unityContainer.Resolve<IRepositoryA>(context2);
Run Code Online (Sandbox Code Playgroud)

RepositoryA并且RepositoryB都有一个带IDataContext参数的构造函数,我希望Unity使用我传递它的上下文初始化存储库.另请注意,IDataContext未在Unity中注册(我不想要3个实例IDataContext).

Exi*_*ist 71

截至今天,他们已添加此功能:

这是最新的下降:

http://unity.codeplex.com/SourceControl/changeset/view/33899

在这里讨论它:

http://unity.codeplex.com/Thread/View.aspx?ThreadId=66434

例:

container.Resolve<IFoo>(new ParameterOverrides<Foo> { { "name", "bar" }, { "address", 42 } });"
Run Code Online (Sandbox Code Playgroud)

  • 链接http://unity.codeplex.com/SourceControl/changeset/view/33899未激活 (5认同)
  • "Class'Microsoft.Practices.Unity.ParameterOverrides'没有类型参数".我正在使用Unity 3.5; 这段代码只适用于较旧版本的Unity吗? (2认同)

ang*_*son 37

<2美分>

如果您以后决定使用需要多于或少于上下文的其他服务,该怎么办?

构造函数参数和IoC的问题在于参数最终与正在使用的具体类型相关联,而不是作为服务接口定义的合同的一部分.

我的建议是你要么解决上下文,我相信Unity应该有办法让你避免构造它的3个实例,或者你应该考虑一个工厂服务,它有一种方法可以构建对象.

例如,如果您以后决定构建一个完全不依赖于传统数据库的存储库,而是使用XML文件为测试生成虚拟数据,该怎么办?您将如何将XML内容提供给该构造函数?

IoC基于解耦代码,通过将参数的类型和语义绑定到具体类型,您实际上没有正确地进行解耦,仍然存在依赖关系.

"这个代码可以与任何类型的存储库通信,只要它实现了这个接口......哦,并使用数据上下文".

现在,我知道其他IoC容器也支持这个,我也在我自己的第一个版本中使用它,但在我看来,它不属于解决步骤.

</ 2美分>

  • 我明白你的观点并同意你的意见,但我仍然需要RepositoryA和RepositoryB的实例拥有相同的IDataContext,它需要与RepositoryC不同.另请注意,IRepositoryA和IRepositoryB具有IDataContext的属性.我稍后会更新示例代码. (3认同)
  • 好点.我正要为构造函数添加一个字符串参数,但在查看这一点后,我决定将它作为一个完整的对象.它只包含此时的字符串,但我已经可以看到如何为它添加更多有用的属性 (2认同)

Kwe*_*wex 7

谢谢你们......我的帖子类似于"存在"的帖子.见下文:

        IUnityContainer container = new UnityContainer();
        container.LoadConfiguration();

        _activeDirectoryService = container.Resolve<IActiveDirectoryService>(new ResolverOverride[]
        {
            new ParameterOverride("activeDirectoryServer", "xyz.adserver.com")
        });
Run Code Online (Sandbox Code Playgroud)


小智 5

您可以使用InjectionConstructor/InjectionProperty/InjectionMethod,具体取决于ResolvedParameter <T>("name")中的注入体系结构,以获取容器中预先注册的Object的实例.

在您的情况下,此Object必须使用Name注册,对于相同的insance,您需要ContainerControlledLifeTimeManager()作为LifeTimeManager.

_unityContainer.RegisterType<IDataContext,DataContextA>("DataContextA", new ContainerControlledLifeTimeManager());
_unityContainer.RegisterType<IDataContext,DataContextB>("DataContextB");

  var repositoryA = _unityContainer.Resolve<IRepositoryA>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextA")));

  var repositoryB = _unityContainer.Resolve<IRepositoryB>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextA")));

  var repositoryA2 = _unityContainer.Resolve<IRepositoryA>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextB")));
Run Code Online (Sandbox Code Playgroud)

  • 你确定这个代码吗?它不编译...`Resolve`采用`ResolverOverride`的集合,而'InjectionConstructor`不是`ResolverOverride`. (4认同)