简体   繁体   中英

Autofac factory for a static method

I have a component in my application with an interface that looks like this:

interface ILogger : IService
{
    Task LogAsync(Message message);
}

I need to construct these instances using a static method:

ILogger logger = ServiceProxy.Create<ILogger>(new Uri(...), new ServicePartitionKey(...));

This is problematic for my unit testing so I am instantiating with a delegate factory with Autofac:

public class LogConsumer
{
    private Func<Uri, ServicePartitionKey, ILogger> _logFactory;
    public LogConsumer(Func<Uri, ServicePartitionKey, ILogger> logFactory)
    {
        _logFactory = logFactory;
    }

    public async Task MethodThatUsesLogger()
    {
        ILogger logger = _logFactory(new Uri(...), new ServicePartitionKey(...));

        await logger.LogAsync(...);           
    }
}

I am registering in Autofac like so:

builder.Register<ILogger>(ctx => (uri, key) => ServiceProxy.Create<ILogger>(uri, key));
  • If I need to register 10 different interfaces in the same way, can I do it in one line with generics?
  • Is there a way to do this without injecting Func and doing it more like Ninject.Extensions.Factory?

You can do what you want by implementing IRegistrationSource

class FactoryRegistrationSource<TService> : IRegistrationSource
{

    public Boolean IsAdapterForIndividualComponents
    {
        get
        {
            return false;
        }
    }

    public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
    {
        IServiceWithType typedService = service as IServiceWithType;
        if (typedService == null)
        {
            yield break;
        }

        if (typedService.ServiceType == typeof(TService))
        {
            IComponentRegistration registration = RegistrationBuilder.ForDelegate<Func<Uri, TService>>((c, p) => ((Uri uri) => Factory.Get<TService>(uri)))
                                                                     .CreateRegistration();

            yield return registration;
        }
    }
}

You would have to register it like this :

builder.RegisterSource(new FactoryRegistrationSource<ILogger>());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM