prlcutting
prlcutting

Reputation: 379

When is DryIoc's IfAlreadyRegistered.Keep setting evaluated?

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

Answers (1)

Progman
Progman

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

Related Questions