-
-
Notifications
You must be signed in to change notification settings - Fork 120
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
One singleton for different types #461
Comments
Hi @Karnah Try this
|
Thanks for quick answer! |
The solution is ok for non-generic types like container.RegisterSingleton(typeof(IFoo), typeof(Foo));
container.RegisterSingleton(typeof(IFoo2), f => f.GetInstance(typeof(IFoo)));
container.GetInstance<IFoo>() == container.GetInstance<IFoo2>(); but it does not work with open generics.. container.RegisterSingleton(typeof(IFoo<>), typeof(Foo<>));
container.RegisterSingleton(typeof(IFoo2<>), f => f.GetInstance(typeof(IFoo<>)));
container.GetInstance<IFoo<string>>() == container.GetInstance<IFoo2<string>>()
I think it would be much more convenient, if the register-method could detect the equal implementation. This is what I would expect (and prefer) to work container.RegisterSingleton(typeof(IFoo<>), typeof(Foo<>));
container.RegisterSingleton(typeof(IFoo2<>), typeof(Foo<>));
container.GetInstance<IFoo<string>>() == container.GetInstance<IFoo2<string>>() |
You can get around this problem with the var container = new ServiceContainer();
container.Register(typeof(FooBar<>), new PerContainerLifetime());
container.RegisterFallback((t,s) => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IFoo<>), sr => {
var fooBarType = typeof(FooBar<>).MakeGenericType(sr.ServiceType.GetGenericArguments());
return sr.ServiceFactory.GetInstance(fooBarType);
}, new PerContainerLifetime());
container.RegisterFallback((t,s) => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IBar<>), sr => {
var fooBarType = typeof(FooBar<>).MakeGenericType(sr.ServiceType.GetGenericArguments());
return sr.ServiceFactory.GetInstance(fooBarType);
}, new PerContainerLifetime());
var fooBar = container.GetInstance<FooBar<int>>();
var foo = container.GetInstance<IFoo<int>>();
var bar = container.GetInstance<IFoo<int>>();
Debug.Assert(ReferenceEquals(fooBar, foo));
Debug.Assert(ReferenceEquals(fooBar, bar));
public interface IFoo<T>{}
public interface IBar<T>{}
public class FooBar<T> : IFoo<T>, IBar<T>{} We can even put this behind an extension method like this public static IServiceRegistry Associate(this IServiceRegistry registry, Type serviceType, Type withServiceType)
{
registry.RegisterFallback
(
(t,s) => t.IsGenericType && t.GetGenericTypeDefinition() == serviceType,
sr => sr.ServiceFactory.GetInstance(withServiceType.MakeGenericType(sr.ServiceType.GetGenericArguments())),
new PerContainerLifetime()
);
return registry;
} Then we are left with this var container = new ServiceContainer();
container.Register(typeof(FooBar<>), new PerContainerLifetime());
container.Associate(typeof(IFoo<>), typeof(FooBar<>));
container.Associate(typeof(IBar<>), typeof(FooBar<>));
var fooBar = container.GetInstance<FooBar<int>>();
var foo = container.GetInstance<IFoo<int>>();
var bar = container.GetInstance<IFoo<int>>();
Debug.Assert(ReferenceEquals(fooBar, foo));
Debug.Assert(ReferenceEquals(fooBar, bar)); |
That's my workaround, thanks. |
Great 👍 |
Good day. I use version 5.2.1 on .Net 4.7.2.
I have interface IClass and two classes BaseClass (inherit IClass) and MainClass (inherit BaseClass). I need resolve the same sigleton for all three types . I use next code:
Problem - Create() method registers Class as transient and RegisterInstance not override this. This was unexpected for me. I decided that main is first registration. Then I've wrote this:
And Create() method has overrided PerContainerLifetime()! Now I use second way, but use with TryGetInstance(). It seems to me this moment can be unobvious not only for me.
The text was updated successfully, but these errors were encountered: