Autofac 等同于 NInject 的 ToMethod() 和开放泛型

Autofac equivalent of NInject's ToMethod() with open generics

我正在尝试从 NInject 迁移到 Autofac,但我 运行 遇到了一个看似简单的问题。我想迁移这个 NInject 绑定:

Kernel.Bind(typeof(IOptions<>)).ToMethod(c => CreateOptions(c.Request.Service));

换句话说,当需要关闭 IOptions<> 时,请使用请求的类型调用 CreateOptions() 并让我创建实现。

我在 Autofac 中想到的最好的是:

  1. 创建 IOptions<> 的虚拟实现,让 Autofac 使用 RegisterGeneric() 构造它,然后在 OnActivating 事件中使用 ReplaceInstance()
  2. 创建一个 IRegistrationSource 按类型过滤然后调用我的工厂方法。

方法 (1) 似乎很愚蠢 - 当然我不必为了获取其类型而创建未使用的对象?

方法 (2) 没问题,但它是大量 代码(见下文),如果我想设置范围等,它会变得更大

在这两种情况下,简单地委托给工厂方法的代码量似乎很大。有没有更好的方法?

(为了完整起见,下面是我的 IRegistrationSource。请注意必须覆盖两个抽象成员才能获得 NInject 功能。)

public abstract class DelegatingRegistrationSource : IRegistrationSource
{
    protected abstract bool CanDelegate(Type limitType);
    protected abstract DelegateActivator CreateDelegate(Type limitType);

    public IEnumerable<IComponentRegistration> RegistrationsFor(Service service,
        Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
    {
        if (!(service is IServiceWithType swt) || !CanDelegate(swt.ServiceType))
            return Enumerable.Empty<IComponentRegistration>();

        var registration = new ComponentRegistration(
            Guid.NewGuid(),
            CreateDelegate(swt.ServiceType),
            new CurrentScopeLifetime(),
            InstanceSharing.None,
            InstanceOwnership.OwnedByLifetimeScope,
            new[] { service },
            new Dictionary<string, object>());

        return new IComponentRegistration[] { registration };
    }

    public bool IsAdapterForIndividualComponents => false;
}

你让我想到了这个!

除了您现在已经掌握的机制之外,我想不出更好的方法来解决这个问题。你可以用开放的通用装饰器做一些事情,但你仍然需要虚拟类型,它并不比 OnActivating 解决方案好多少。

这就是某种 OnActivating 事件的用途,对激活实例进行高级替换。

如果您愿意在我们的回购协议 (http://github.com/autofac/autofac) 中提出一个问题作为功能请求,并提供所有细节,我愿意讨论 'ideal' 行为的外观如果我们将它添加到库中,以及用例是否足够常见以添加。