I'm trying to register a singleton using DryIoc, but container is returning multiple instances of my singleton class. The singleton class is registered as the implementation type for multiple different service interfaces. When any of the aforementioned service interfaces is requested from DryIoc, I expect to get the same instance of my singleton class back, but that's not happening and I don't know why.
Here's a basic example of what I'm trying to do. In this example, I have a class, Foo
that I would like to use as the singleton implementation for interfaces IFoo
and IBar
. In other words, when either IFoo
or IBar
are resolved from the container, I'd like for the same instance of Foo
to be returned.
interface IFoo
{
}
interface IBar
{
}
class Foo : IFoo, IBar
{
}
Container container = new Container();
container.Register<IFoo, Foo>(Reuse.Singleton);
container.Register<IBar, Foo>(Reuse.Singleton);
object foo = container.Resolve<IFoo>();
object bar = container.Resolve<IBar>();
Assert.AreSame(foo, bar); // Why does this fail?
I've considered using DryIoc's RegisterInstance
method but that would require the class to be manually created and I'm trying to avoid that because, unlike the simplified example above, the real-world class has dependencies of its own.
The Register
method adds separate / independent registrations to the container. You need to specifically say to use the same registration for multiple services.
// registers with Foo interfaces and itself. Remove @nonPublicServiceTypes to restrict for public types
container.RegisterMany<Foo>(Reuse.Singleton, nonPublicServiceTypes: true);
Assert.AreSame(container.Resolve<IFoo>(), container.Resolve<IBar>());
container.Register<IFoo, Foo>(Reuse.Singleton);
container.RegisterMapping<IBar, IFoo>(); // maps to the IBar registration
Assert.AreSame(container.Resolve<IFoo>(), container.Resolve<IBar>());
Manually delegate the resolution as in @Fyodor answer.
DryIoc's concept of "reuse" applies to services, not implementations. Your registrations are for two different services (IFoo
and IBar
), so they get different reuses, and the fact that they share implementation (Foo
) does not apply here.
To achieve your goal, you can register the services via made
that redirects to the implementation:
container.Register<Foo>( Reuse.Singleton );
container.Register<IFoo, Foo>( made: Made.Of( () => ReturnThis( Arg.Of<Foo>() ) ), reuse: Reuse.Singleton );
container.Register<IBar, Foo>( made: Made.Of( () => ReturnThis( Arg.Of<Foo>() ) ), reuse: Reuse.Singleton );
// Where ReturnThis is define thusly:
static T ReturnThis<T>( T t ) => t;
(you need the ReturnThis
call, because naked Made.Of( () => Arg.Of<Foo>() )
doesn't work; Made
always expects a method call)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With