具有开放式泛型的NInject ToMethod的Autofac等效项

问题描述

我正在尝试从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)中提出问题,请提供所有详细信息,我愿意讨论如果添加它,“理想”行为的外观到库中,以及用例是否足够通用以便添加。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...