Open RonHeck opened 4 years ago
BuilderContext
is rather expensive and I am trying to avoid allocating new one unless it is absolutely necessary. Why is it a problem for you?
I have multiple registrations for the same interface differ by the registered name. Most implementations are decorators. I created an extension to define how each decorator resolves the dependency on the interface. Mainly this is only a definition, which name to use for resolving. The extension then simply adds ResolveOverrides to the context. This logic is only enabled, if the context has no ResolveOverrides defined to prevent interfere of resolving with overrides. This way I try to prevent "poluting" my business code with framework specific attributes.
I agree that creating a BuilderContext for resolving each dependency is a performance hit. I have to check if it is possible to merge ResolveOverrides provided from the "external" resolve call with the internally created ResolveOverrides of the extension in a propper way.
Nevertheless I did not expect, that the ResolveOverrides, defined for the resolve call also effect resolving of the inner dependencies. There is no way to define, that the ResolveOverride should only take into account for a specific resolving type. Rather it will override all dependencies in the resolve hierarchy.
Imagine following scenario using the types of the example above:
I register type Xyz
as singleton. Now resolve Foo
with the override. Finally, if the singleton is not created yet, the singleton will created with the OverrideAbc
. If I now resolve Foo
without override, the singleton is reused. At the end this may leads to an runtime dependent behavior of Xyz
if the code can not guarentee if Foo
is created with or without override first. Also this behavior seems not to be transparent to the API user.
I also already thought about not to recreate the BuilderContext each time but using an hierachical structure to manage the overrides for each resolve call. Resolving within the same builder context is an synchrone process and mainly recursive. So before calling Resolve
of the parameter type I can store the overrides localy and set the Overrides of the context to Array.Empty
. In my mind this should not result in expensive heap allocating.
A new unity is going to be using struct as a context and will not allocate anything.
Even better. Nevertheless could You understand my concerns? I'm not sure if I could put it into understandable terms.
I think I do but I can’t look into this closer right this moment...
There is a Target parameter on override type, did you try to use it?
I currently tried but it had no effect. I used
var foo = unityContainer.Resolve<Foo>(new DependencyOverride(typeof(Foo), typeof(IAbc), null, dummyAbc));
For my Extension this might be an option, but it also should work with the default builder strategies of UnityContainer, right?
Description
I have a wrapper type
Foo
with ctorFoo(IAbc,IXyz).
I want to resolveFoo
usingUnityContainer.Resolve
. I provide a ResolverOverride forIAbc
to the call. When the container resolves the dependencies of types constructor, it uses the BuilderContext ofFoo
to resolveIXyz
which also includes the ResolverOverride forIAbc
. Regarding inversion of control this seems to be wrong as the caller ofResolve<Foo>()
should not know howIXyz
is resolved and therefore should not "accidentally" influence resolvingIXyz
(e.g. ifIXyz
resolves to a type that depends onIAbc
.To Reproduce
Please provide UnitTest in the form of:
Additional context
Used Version 5.11.8 of unity container nuget to verify. Test was written with NUnit so may it has to be adjust to the used test framework.