Programing

Unity의 Resolve () 메서드에 생성자 매개 변수를 전달할 수 있습니까?

lottogame 2020. 9. 14. 21:35
반응형

Unity의 Resolve () 메서드에 생성자 매개 변수를 전달할 수 있습니까?


종속성 주입을 위해 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그리고 RepositoryB모두가 사용하는 생성자가 IDataContext매개 변수를, 그리고 유니티 내가 그것을 통과하는 상황으로 저장소를 초기화 할 수 있습니다. 또한 IDataContextUnity에 등록되어 있지 않습니다 (의 인스턴스 3 개를 원하지 않음 IDataContext).


오늘부터 다음과 같은 기능을 추가했습니다.

여기 최신 드롭에 있습니다.

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 } });"

<2 센트>

나중에 컨텍스트보다 더 많거나 적은 다른 서비스를 사용하기로 결정하면 어떻게됩니까?

생성자 매개 변수 및 IoC의 문제는 매개 변수가 서비스 인터페이스가 정의하는 계약의 일부가 아니라 궁극적으로 사용중인 구체적인 유형에 연결된다는 것입니다.

제 제안은 컨텍스트를 해결하고 Unity가 3 개의 인스턴스를 생성하는 것을 피할 수있는 방법이 있어야한다고 생각하거나 객체를 생성하는 방법이있는 팩토리 서비스를 고려해야한다고 생각합니다.

예를 들어, 나중에 기존 데이터베이스에 전혀 의존하지 않고 대신 XML 파일을 사용하여 테스트 용 더미 데이터를 생성하는 저장소를 구성하기로 결정하면 어떻게 될까요? XML 콘텐츠를 해당 생성자에 어떻게 공급 하시겠습니까?

IoC는 디커플링 코드를 기반으로합니다. 인수의 유형과 의미를 구체적인 유형에 묶음으로써 실제로 디커플링을 제대로 수행하지 못했지만 여전히 종속성이 있습니다.

"이 코드는이 인터페이스를 구현하는 한 가능한 모든 유형의 저장소와 통신 할 수 있습니다 .... 아, 그리고 데이터 컨텍스트를 사용합니다."

이제 다른 IoC 컨테이너가이를 지원한다는 것을 알고 있으며 제 첫 번째 버전에서도 사용했지만 제 생각에는 해결 단계에 속하지 않습니다.

</ 2 센트>


고마워요 ... 내 게시물은 "Exist"의 게시물과 유사합니다. 아래를 참조하십시오.

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

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

ResolvedParameter <T> ( "name") 내의 주입 아키텍처에 따라 InjectionConstructor / InjectionProperty / InjectionMethod를 사용하여 컨테이너에서 사전 등록 된 객체의 인스턴스를 가져올 수 있습니다.

In your case this Object must be registered with a Name, and for the same insance you need ContainerControlledLifeTimeManager() as the 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. 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.

You could take a small step back from full DI and make your repository implementations responsible for establishing their own data contexts. 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.

First, I would use a LifetimeManager to manage the lifecycle and number of instances of IDataContext that Unity creates.
http://msdn.microsoft.com/en-us/library/cc440953.aspx

It sounds like the ContainerControlledLifetimeManager object will give you the instance management that you need. With that LifetimeManager in place, Unity should add the same instance of the IDataContext to all objects that require an IDataContext dependency.

참고URL : https://stackoverflow.com/questions/787001/can-i-pass-constructor-parameters-to-unitys-resolve-method

반응형