Register multiple singletons with same interface but different constructor parameters

前端 未结 2 2013
无人及你
无人及你 2021-01-15 05:00

I have 2 storage (Azure) accounts lets call them src and dest and I have controllers that require access to both and I\'m trying to work out how to register these 2 singleto

相关标签:
2条回答
  • 2021-01-15 05:34

    I would suggest defining two new interfaces:

    public interface IBlobAccessClientSource : IBlobAccessClient
    { }
    
    public interface IBlobAccessClientDestination : IBlobAccessClient
    { }
    

    And then registering them both individually (in whatever way that SimpleInject supports).

    Then in your consumers, inject in IBlobAccessClientSource and / or IBlobAccessClientDestination as needed. This will ensure that there are two singleton registrations - one for each of the two interfaces.

    0 讨论(0)
  • 2021-01-15 05:52

    There is a non-generic RegisterConditional overload that accepts a Registration object. You can wrap your BlobAccessClient instance in a Registration and pass it on to RegisterConditional as shown here:

    container.RegisterConditional(typeof(IBlobAccessClient),
        Lifestyle.Singleton.CreateRegistration(
            () => new BlobAccessClient(srcConnectionString), container),
        c => c.Consumer.Target.Parameter.Name.Contains("src"));
    
    container.RegisterConditional(typeof(IBlobAccessClient),
        Lifestyle.Singleton.CreateRegistration(
            () => new BlobAccessClient(destConnectionString), container),
        c => c.Consumer.Target.Parameter.Name.Contains("dest"));
    

    If this is a common pattern, you can simplify your code a bit by defining a simple extension method as follows:

    public static void RegisterConditionalInstance<TService>(
        this Container container, TService instance, Predicate<PredicateContext> predicate)
        where TService : class
    {
        container.RegisterConditional(typeof(TService),
            Lifestyle.Singleton.CreateRegistration(() => instance, container),
            predicate);
    }
    

    This allows you to reduce the previous configuration to the following:

    container.RegisterConditionalInstance<IBlobAccessClient>(
        new BlobAccessClient(srcConnectionString),
        c => c.Consumer.Target.Parameter.Name.Contains("src"));
    
    container.RegisterConditionalInstance<IBlobAccessClient>(
        new BlobAccessClient(destConnectionString),
        c => c.Consumer.Target.Parameter.Name.Contains("dest"));
    

    Optionally, you can simplify the predicate by extracting this to a simple method as well:

    private static Predicate<PredicateContext> InjectedIntoTargetNamed(string targetName) =>
        c => c.Consumer.Target.Name.Contains(targetName);
    

    This reduces the registration to the following:

    container.RegisterConditionalInstance<IBlobAccessClient>(
        new BlobAccessClient(srcConnectionString),
        InjectedIntoTargetNamed("src"));
    
    container.RegisterConditionalInstance<IBlobAccessClient>(
        new BlobAccessClient(destConnectionString),
        InjectedIntoTargetNamed("dest"));
    
    0 讨论(0)
提交回复
热议问题