Reputation: 379
Using DryIoc, if I have a service, IService
, and two implementations, ServiceA
and ServiceB
, registered in that order (ServiceA
then ServiceB
) with Reuse.Singleton
lifetime (don't know if that matters or not, but not sure why it would), and ServiceA
is registered with the setting IfAlreadyRegistered.Keep
, when a type IService
is later resolved (by constructor injection of some other class), should I expect to get an instance of ServiceA
, or ServiceB
?
The reason I ask the question is because I want to provide a default implementation for IService
in a shared library (ServiceA
), but if another party registers an implementation (ServiceB
), then I want to favor that one. I think I can achieve this with the IfAlreadyRegistered.Keep
option for ServiceA
, but the notion of "keeping" an implementation strongly suggests a dependency on the order of registration. In other words, if ServiceA
is registered first, then no other implementations for IService
would exist at that point, so I would expect that IfAlreadyRegistered.Keep
would just register itself in the same way as if IfAlreadyRegistered
were not explicitly set at all.
To my surprise, I found that regardless of the order of registration, (A then B, or B then A), ServiceA
was resolved both times. This suggests that perhaps the notion of "keeping" a registration is deferred and evaluated not at the point of registration, and perhaps at the point of resolution.
By contrast however, if I register both implementations with IfAlreadyRegistered.Throw
(instead of IfAlreadyRegistered.Keep
), then whichever implementation is registered last immediately throws an exception at the point of registration. I highlight this because it appears that it behaves differently than the IfAlreadyRegistered.Keep
setting in terms of the point when the IfAlreadyRegistered
setting is evaluated.
To reiterate, my main question is in the first paragraph. If however there is a better technique for achieving my goal outlined in the first sentence of my second paragraph, then please do share!
Upvotes: 0
Views: 33
Reputation: 19555
You can use IfAlreadyRegistered.Replace
for the second implementation. That way it will "override" the previous registration, see https://github.com/dadhi/DryIoc/blob/master/docs/DryIoc.Docs/RegisterResolve.md#registerplaceholder and https://github.com/dadhi/DryIoc/blob/4697be13aceb1ce985a2f3481f233a27c4c69e0b/src/DryIoc/Container.cs#L14828:
public enum IfAlreadyRegistered : byte { [...] /// <summary>Replaces old registration with new one.</summary> Replace, [...] }
Check the following example code:
public interface IService;
public class ServiceA : IService;
public class ServiceB : IService;
public class Program
{
static void Main(string[] args)
{
var container = new Container();
container.Register<IService, ServiceA>();
var service = container.Resolve<IService>();
Console.WriteLine(service);
container.Register<IService, ServiceB>(ifAlreadyRegistered: IfAlreadyRegistered.Replace);
var service2 = container.Resolve<IService>();
Console.WriteLine(service2);
}
}
This will generate the following output:
ServiceA
ServiceB
Upvotes: 0