Autofac 解析相同类型的多个实例

Posted

技术标签:

【中文标题】Autofac 解析相同类型的多个实例【英文标题】:Autofac resolves multiple instances of the same type 【发布时间】:2015-05-11 04:37:22 【问题描述】:

我的应用程序中处理命令处理的Mediatr 略有修改版本。我已经实现了一个 MediatorPipeline,它允许我拥有前处理器和后处理器。

public class AsyncMediatorPipeline<TRequest, TResponse> 
    : IAsyncRequestHandler<TRequest, TResponse> 
    where TRequest : IAsyncRequest<TResponse>

    private readonly IAsyncRequestHandler<TRequest, TResponse> inner;
    private readonly IAsyncPreRequestHandler<TRequest>[] preRequestHandlers;
    private readonly IAsyncPostRequestHandler<TRequest,TResponse>[] postRequestHandlers;

    public AsyncMediatorPipeline(IAsyncRequestHandler<TRequest, TResponse> inner, 
        IAsyncPreRequestHandler<TRequest>[] preRequestHandlers, 
        IAsyncPostRequestHandler<TRequest, TResponse>[] postRequestHandlers)
    
        this.inner = inner;
        this.preRequestHandlers = preRequestHandlers;
        this.postRequestHandlers = postRequestHandlers;
    

    public async Task<TResponse> Handle(TRequest message)
    
        foreach (var preRequestHandler in preRequestHandlers)
        
            await preRequestHandler.Handle(message);
        

        var result = await inner.Handle(message);

        foreach (var postRequestHandler in postRequestHandlers)
        
            await postRequestHandler.Handle(message, result);
        

        return result;
    

我正在使用 autofac 注册我的预处理器,如下所示:

builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
    .As(type => type.GetInterfaces()
        .Where(type => type.IsClosedTypeOf(typeof(IAsyncPreRequestHandler<>))))
    .InstancePerLifetimeScope();

在运行时,我得到了重复的预处理器。我必须过滤删除重复项的集合。我不确定为什么会这样。如果我注释掉注册,我没有得到任何预处理器,这表明我没有在其他地方复制注册。

更新:以下是有关似乎被注册两次的类型的更多详细信息。各种类定义:

具体的处理程序

public class ClientEditorFormIdentifierValidationHandler 
: IAsyncPreRequestHandler<AddOrEditClientCommand>

命令类

public class AddOrEditClientCommand 
: IAsyncRequest<ICommandResult>

命令界面

public interface IAsyncRequest<out TResponse>  

【问题讨论】:

您在某处使用.AsImplementedInterfaces() 吗?或AppDomain.CurrentDomain.GetAssemblies() ?如果您在builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies()).AsImplementedInterfaces() 之前添加注册,CLR 将加载您的程序集,您将有 2 个注册。如果您评论您的注册,CLR 将不会加载您的程序集,您也不会进行任何注册。 GetAssemblies 将只返回已被 CLR 加载的程序集 我不认为它被注册了两次。如果我注释掉上面的注册,则类型根本无法解析。我的印象是这个注册实际上是注册类型两次,但我对 autofac 不够熟悉,无法弄清楚为什么或如何。 我看不出注册两次的任何原因。你使用AppDomain.CurrentDomain.GetAssemblies() 吗?你确定你的程序集在你注册你的类型时已经加载了吗? 嗨@CyrilDurand,我添加了一些关于被复制的特定类型的更多细节。我没有在解决方案中的任何地方使用 GetAssemblies() 方法。 很遗憾,我无法重现该问题。我想我的代码和你的一样,但我只有一次注册(AsImplementedInterfaces 除外,它给了我 2 个注册)。如果您查看container.ComponentRegistry.RegistrationsFor(new TypedService(typeof(IAsyncPreRequestHandler&lt;AddOrEditClientCommand&gt;)));,您应该有 2 个结果,并且您可能会找到更多信息。 【参考方案1】:

经过大量故障排除后,我发现我实际上注册了我的处理程序两次。我喜欢使用 Autofac 模块将容器的配置分解为可管理的块。

在我的 MVC5 启动类中,我像这样注册我的模块:

builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly());

深埋在“InfrastructureModule”类中的是一行:

builder.RegisterModule<MediatorModule>();

这当然是重新注册我的中介处理程序... DUH..

【讨论】:

我有过非常相似的经历(包括“duh”时刻:)。我的通知处理程序被调用了两次。那是因为他们注册了两次。使用builder.RegisterAssemblyTypes(typeof(MyType).Assembly).AsImplementedInterfaces... 方法很容易意外地注册它们两次,因为当然,您的程序集包含许多类,因此您可以用很多东西代替MyType。 github.com/jbogard/MediatR/issues/501

以上是关于Autofac 解析相同类型的多个实例的主要内容,如果未能解决你的问题,请参考以下文章

[Asp.Net Core]Autofac抽象多实现的问题

如何运用AutoFac在WebAPI中注入多个接口

FragmentManager 添加多个相同 Fragment 类型的实例

Autofac之自动装配

如何在 Core Data 中为多个对象(相同实体类型)生成数组实例?

如何确认在多个服务器实例上是否完成了相同的任务