Register multiple singletons with same interface but different constructor parameters

烈酒焚心 提交于 2019-12-01 11:38:26

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"));

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!