Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Singleton with multiple interfaces - idiosyncrasies depending on underlying container #23

Open
1 of 2 tasks
szaboopeeter opened this issue Apr 3, 2022 · 3 comments
Open
1 of 2 tasks
Labels
enhancement New feature or request

Comments

@szaboopeeter
Copy link
Member

Feature request

Type

  • - Enhancement - completely new feature
  • - Improvement - make what we have better

Is your feature request related to a problem?

I have web api that was using Unity container with Agoda.IoC on top of it. I was playing around with it, trying to get rid of Unity in favor of the AspNetCore DI. Since we're talking small api, this was fairly easy to do, but some of my integration tests became flaky after this process. Turns out I have a service class, that implements, and is registered into the DI multiple interfaces.

It looks like that when this scenario is used with unity, it will resolve the same instance for each registered interface - this seems to be the desired behavior, since there is even a test for it:

[Test]
public void RegisterByAttribute_WithMultipleAttributes_CanResolveAll()
{
_container.RegisterByAttribute(false, typeof(MultipleAttributes).Assembly);
var result1 = _container.Resolve<IMultipleAttributes1>();
var result2 = _container.Resolve<IMultipleAttributes2>();
Assert.AreEqual(typeof(MultipleAttributes), result1.GetType());
Assert.AreSame(result1, result2);
}

Turns out that my application depends on this behavior, and this works differently if the underlying container is the default asp.net core container. A quick test in MicrosoftExtensionsDependencyInjectionAutowireTests seems to prove this (note that the passing test condition is AreNotSame() in this case):
image

Describe the solution you'd like

Depending whether we want the annotations to behave in the same way regardless of the underlying container, we should either change the default behavior of these implementations to be aligned, or discuss whether this is even a scenario that we want to support in case of .Net DI. If we want to support both methods, we can come up with an "overloaded syntax", something like:

[RegisterSingleton(For = new[]{typeof(IMultipleAttributes1), typeof(IMultipleAttributes2) })]

Additional context

Actually this is a little tricky to do with aspnet di as it is not supported out of box, but not impossible. See aspnet/DependencyInjection#360

@szaboopeeter szaboopeeter added the enhancement New feature or request label Apr 3, 2022
@szaboopeeter szaboopeeter changed the title Resolved instance idiosyncrasies depending on underlying container Singleton with multiple interfaces - idiosyncrasies depending on underlying container Apr 3, 2022
@dicko2
Copy link
Contributor

dicko2 commented Apr 4, 2022

I think the root cause here is that the unit tests are different. I think what we should do is refactor them to test an abstraction that wraps the container.

So you have a single set of unit tests and each containers project implements that abstraction and reuses a core set of tests.

From memory all the tests do is

  • build container
  • check a list of what's registered

So should be a fairly simple abstraction

@szaboopeeter
Copy link
Member Author

@dicko2 Yes, unit tests are different and we can think of a way to reorganize them, but what I was trying to do here is use unit tests to show that the behavior is different, and depending on the underlying IoC container, some behaviors may not even be achievable (eg: today I can't get the same instance resolved for a singleton that implements two interfaces, via the two interfaces using asp.net default container with Agoda.IoC attributes. I can do the same if I use Unity (and maybe Autofac?)).

@kchinburarat
Copy link
Contributor

kchinburarat commented Apr 24, 2023

@szaboopeeter
Can we write the code like this

[RegisterSingleton(For = typeof(IMultipleAttributes1))]
[RegisterSingleton(For = typeof(IMultipleAttributes2))]
public class MultipleAttribute : IMultipleAttributes1 , IMultipleAttributes2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants