简体   繁体   English

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

[英]Can I pass constructor parameters to Unity's Resolve() method?

I am using Microsoft's Unity for dependency injection and I want to do something like this: 我使用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);

RepositoryA and RepositoryB both have a constructor that takes an IDataContext parameter, and I want Unity to initialize the repository with the context that I pass it. RepositoryARepositoryB都有一个带有IDataContext参数的IDataContext函数,我希望Unity使用我传递它的上下文初始化存储库。 Also note that IDataContext is not registered with Unity (I don't want 3 instances of IDataContext ). 另请注意, IDataContext未在Unity中注册(我不想要3个IDataContext实例)。

As of today they have added this functionality: 截至今天,他们已添加此功能:

It's in the latest drop here: 这是最新的下降:

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

Discussion on it here: 在这里讨论它:

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

Example: 例:

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

< 2 cents> <2美分>

What if you later on decide to use a different service that requires more or less than just the context? 如果您以后决定使用需要多于或少于上下文的其他服务,该怎么办?

The problem with constructor parameters and IoC is that the parameters are ultimately tied to the concrete type being used, as opposed to being part of the contract that the service interface defines. 构造函数参数和IoC的问题在于参数最终与正在使用的具体类型相关联,而不是作为服务接口定义的合同的一部分。

My suggestion would be that you either resolve the context as well, and I believe Unity should have a way for you to avoid constructing 3 instances of it, or you should consider a factory service that has a way for you to construct the object. 我的建议是你要么解决上下文,我相信Unity应该有办法让你避免构造它的3个实例,或者你应该考虑一个工厂服务,它有一种方法可以构建对象。

For instance, what if you later on decide to construct a repository that doesn't rely on a traditional database at all, but instead use an XML file to produce dummy-data for the test? 例如,如果您以后决定构建一个完全不依赖于传统数据库的存储库,而是使用XML文件为测试生成虚拟数据,该怎么办? How would you go about feeding the XML content to that constructor? 您将如何将XML内容提供给该构造函数?

IoC is based around decoupling code, by tying in the type and semantics of the arguments to the concrete types, you really haven't done the decoupling correctly, there's still a dependency. IoC基于解耦代码,通过将参数的类型和语义绑定到具体类型,您实际上没有正确地进行解耦,仍然存在依赖关系。

"This code can talk to any type of repository possibly, as long as it implements this interface.... Oh, and uses a data context". “这个代码可以与任何类型的存储库通信,只要它实现了这个接口......哦,并使用数据上下文”。

Now, I know that other IoC containers have support for this, and I had it in my first version of my own as well, but in my opinion, it doesn't belong with the resolution step. 现在,我知道其他IoC容器也支持这个,我也在我自己的第一个版本中使用它,但在我看来,它不属于解决步骤。

< /2 cents> </ 2美分>

Thanks guys ... mine is similar to the post by "Exist". 谢谢你们......我的帖子类似于“存在”的帖子。 See below: 见下文:

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

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

You can use InjectionConstructor / InjectionProperty / InjectionMethod depending on your Injection Architecture within the ResolvedParameter< T >("name") to get a instance of a pre-registered Object in the container. 您可以使用InjectionConstructor / InjectionProperty / InjectionMethod,具体取决于ResolvedParameter <T>(“name”)中的注入体系结构,以获取容器中预先注册的Object的实例。

In your case this Object must be registered with a Name, and for the same insance you need ContainerControlledLifeTimeManager() as the LifeTimeManager. 在您的情况下,此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")));

The very short answer is: no. 答案非常简短:没有。 Unity currently has no way to pass parameters into the constructor that aren't constant or injected, that I have been able to find. Unity目前无法将参数传递给非常量或注入的构造函数,这是我能够找到的。 IMHO that's the single biggest thing it's missing, but I think it is by design rather than by omission. 恕我直言,这是它失踪的最大的一件事,但我认为这是设计而不是遗漏。

As Jeff Fritz notes, you could in theory create a custom lifetime manager that knows which context instance to inject into various types, but that's a level of hard-coding which seems to obviate the purpose of using Unity or DI in the first place. 正如Jeff Fritz指出的那样,理论上你可以创建一个自定义生命周期管理器来知道要注入各种类型的上下文实例,但这是一个硬编码级别,它似乎首先消除了使用Unity或DI的目的。

You could take a small step back from full DI and make your repository implementations responsible for establishing their own data contexts. 您可以从完整的DI中退一步,让您的存储库实现负责建立自己的数据上下文。 The context instance can still be resolved from the container but the logic for deciding which one to use would have to go into the implementation of the repository. 仍然可以从容器中解析上下文实例 ,但是决定使用哪一个的逻辑必须进入存储库的实现。 It's not as pure, certainly, but it would get rid of the problem. 当然,它不是那么纯粹,但它可以摆脱这个问题。

Another alternative you could use (don't really know if it is a good practice or not) is creating two containers and registering an instance for each: 您可以使用的另一种替代方法(不知道它是否是一种好的做法)是创建两个容器并为每个容器注册一个实例:

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


//declare _unityContainer2
IDataContext context2 = _unityContainer2.Resolve<IDataContext>(); //New instance
_unityContainer2.RegisterInstance(context2);
var repositoryA2 = _unityContainer2.Resolve<IRepositoryA>(context2); //will retrieve the other instance

hope this helps too 希望这也有帮助

NotDan, I think you may have answered your own question in comments to lassevk. NotDan,我想你可能已经在对lassevk的评论中回答了你自己的问题。

First, I would use a LifetimeManager to manage the lifecycle and number of instances of IDataContext that Unity creates. 首先,我将使用LifetimeManager来管理Unity创建的IDataContext的生命周期和实例数。
http://msdn.microsoft.com/en-us/library/cc440953.aspx http://msdn.microsoft.com/en-us/library/cc440953.aspx

It sounds like the ContainerControlledLifetimeManager object will give you the instance management that you need. 听起来像ContainerControlledLifetimeManager对象将为您提供所需的实例管理。 With that LifetimeManager in place, Unity should add the same instance of the IDataContext to all objects that require an IDataContext dependency. 有了LifetimeManager,Unity应该将IDataContext的相同实例添加到需要IDataContext依赖项的所有对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用Unity的Resolve &lt;&gt;()方法将参数发送到对象的构造函数? - How to send a parameter to an object's constructor with Unity's Resolve<>() method? 我们可以将 static 成员变量传递给构造函数来解决统一问题吗? - Can we pass static member variables to constructor to resolve unity? unity如何解析构造函数的参数? - How does unity resolve the parameters of a constructor? 如何将类传递给统一的方法? - How can i pass class to method in unity? 我应该将哪些参数传递给ViewModel的构造函数? - What parameters should I pass to my ViewModel's constructor? 我将单例作为参数传递还是手动解析? (统一DI) - Do I pass singletons as parameters or do I manually resolve them? (Unity DI) 为什么可以将匿名方法传递给委托人的构造函数? - Why anonymous method can be pass to a delegator's constructor? 将参数传递给Method Decorator Fody中的构造函数 - Pass parameters to the constructor in Method Decorator Fody 为什么“ resolve”方法总是调用已经在Unity中注册的类构造函数? - Why “resolve” method always calls the class constructor that is already registered in Unity? 我可以在对象的 New() 构造函数中声明一个委托吗? 还是带初始化参数? - Can I declare a delegate in an Object's New() constructor? Or with initialization parameters?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM