Warm tip: This article is reproduced from serverfault.com, please click

c#-Autofac 注册 IEnumerable 和个人来解决它们

(c# - Autofac register IEnumerable and individuals to resolve them all)

发布于 2021-10-20 20:30:27

我们都知道你可以注册多个实例并使用 Autofac 解决它们

builder.RegisterType<Foo1>().As<IFoo>();    
builder.RegisterInstance(new Foo2("something")).As<IFoo>();    
builder.RegisterInstance(new Foo2("another")).As<IFoo>();

//and finally
var foos = ctx.Resolve<IEnumerable<IFoo>>();

现在我必须注册一些 foos 如下:

builder.Register(ctx =>{
   var factory = ctx.Resolve<IFooFactory>();
   var allTheFoos = config.FooConfigs.Select(fooConfig => factory.CreateFoo(fooConfig));
   return allTheFoos;
}).As<IEnumerable<IFoo>>();

这仍然有效,但我认为这不是正确的方法。除此之外,我还想添加一个额外的IFoo注册

builder.RegisterInstance(new Foo2("this one")).As<IFoo>();    

如果我现在解析 IEnumerable,我会将集合显式注册为 IEnumerable,但我需要它还包含 Foo2("this one");

//contains allTheFoos, but not Foo2("this one");
var foos = ctx.Resolve<IEnumerable<IFoo>>();

注册本身不能合并,因为它们在不同的模块中是有原因的。我想我需要单独注册使用工厂创建的 foo,但这需要在 Register 方法(或等效方法)中,因为我需要能够首先解析工厂本身。我希望是这样的:

builder.Register(ctx => /* generate foos*/).AsMultiple<IFoo>();

编辑:根据答案

public class BotRegistrationSource : IRegistrationSource
{
    private readonly IConfiguration _config;

    public BotRegistrationSource(IConfiguration config)
    {
        _config = config;
    }

    public IEnumerable<IComponentRegistration> RegistrationsFor(Service service,
        Func<Service, IEnumerable<ServiceRegistration>> registrationAccessor)
    {
        var swt = service as IServiceWithType;
        if (!(swt?.ServiceType.IsAssignableTo<IBot>() ?? false))
        {
            return Enumerable.Empty<IComponentRegistration>();
        }

        return  _config.GetSection("Bots")
            .GetChildren()
            .Select(c =>
                new ComponentRegistration(
                    Guid.NewGuid(),
                    new DelegateActivator(swt.ServiceType, (componentContext, _) =>
                    {
                        var botFactory = componentContext.Resolve<IBotFactory>();
                        var config = botFactory.CreateConfig();
                        c.Bind(config);
                        var bot = botFactory.Create(config);
                        bot.Enable();
                        return bot;
                    }),
                    new CurrentScopeLifetime(),
                    InstanceSharing.None,
                    InstanceOwnership.OwnedByLifetimeScope,
                    new[] { service },
                    new Dictionary<string, object>()));
    }

    public bool IsAdapterForIndividualComponents => false;
}
Questioner
Stijn Van Antwerpen
Viewed
0
Travis Illig 2021-10-21 21:43:03

我认为你将要查看的是注册源注册源是一种完全按照你的意愿行事的方法——在请求服务时向容器提供一个或多个组件。该文档有一个示例