我有一个简单的项目来尝试Mediatr问题。当我的API的SAME项目中的处理程序的具体类起作用时,它将起作用。但是,当我将该处理程序类带入另一个项目(并且API引用该项目的c)时,它不会解析注册表。

我收到此错误:



我在我的项目中有这个结构,并且还显示了它的工作原理和不工作的地方:

c# - 当实体位于不同的项目中时,Mediatr为什么不解析方法?-LMLPHP

有关更多说明,请参见以下代码:

MyApi2-> Startup.cs:

namespace MyApi2
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddMediatR();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMvc();
        }
    }
}

MyApi2-> ValuesController:
namespace MyApi2.Controllers
{
    [Route("api/[controller]")]
    public class ValuesController : Controller
    {
        private readonly IMediator _mediator;

        public ValuesController(IMediator mediator)
        {
            _mediator = mediator;
        }

        [HttpGet]
        public async Task<IEnumerable<string>> Get()
        {
            try
            {
                var rr = await _mediator.Send(new GetTokenModelRequest());
            }
            catch (Exception ex)
            {
                throw;
            }
            return new string[] { "value1", "value2" };
        }
    }
}

MyBiz-> GetTokenModelRequest
namespace MyBiz
{
    public class GetTokenModelRequest : LoginModel, IRequest<TokenModel>
    {
    }
    public class LoginModel
    {
        public string Username { get; set; }
        public string Password { get; set; }
    }
    public class TokenModel
    {
        #region Properties

        public Guid Id { get; set; }
        public string Username { get; set; }
        public string Token { get; set; }
        public DateTime Expiration { get; set; }

        #endregion
    }
}

MyInftra-> TokenQueryHandler
namespace MyInfra
{
    public class TokenQueryHandler : ITokenQueryHandler
    {
        public Task<TokenModel> Handle(GetTokenModelRequest request, CancellationToken cancellationToken)
        {
            return Task.FromResult(new TokenModel());
        }
    }
}

因此,如果我从TokenQueryHandlerMyInfra进行 MOVE MyApi正常工作,但我应该可以将其引用为项目,对不对?

最佳答案

更新

7.0.0软件包的MediatR.Extensions.Microsoft.DependencyInjection版本开始,调用AppDomain扩展方法时,不再自动扫描AddMediatR()以查找包含要注册的MediatR基本类型的已加载程序集。

实际上,该功能的无参数重载已从包中完全消除,需要用户传递程序集(或类型)来进行扫描。

这使得在每个引用的程序集中注册MediatR基本类型(IRequestHandlerINotificationHandlerIRequestPreProcessorIRequestPostProcessor),由用户控制和自由决定。

因此,如果我们想在MediatR容器中注册的虚构程序Assembly1Assembly2中有一些MediatR基本类型:

而不是:services.AddMediatR();
您需要做:services.AddMediatR(typeof(Assembly1), typeof(Assembly2));
这使我的原始答案(下)对于使用此软件包的版本7(或更高版本)的任何人都是多余的,但对于使用较旧版本的用户,我将保留在这里。

原始答案

注意:以下答案仅与oj​​it_a软件包的
AddMediatR()文件中的startup.cs扩展方法的调用完成了初始化MediatR的许多工作:

  • 它在App Domain中扫描当前加载的程序集
  • 它扫描每个当前加载的程序集,以找到从MediatR基本类型(IRequestHandlerINotificationHandlerIRequestPreProcessorIRequestPostProcessor)继承的每个类
  • 它将每种MediatR基本类型注册到容器中,以供以后使用

  • 考虑到以上几点,理解.NET CLR如何加载引用的程序集很重要。 Rick Strahl有一个非常有趣的MediatR.Extensions.Microsoft.DependencyInjection进入细节,但在这里我将用引号进行总结:



    为什么要知道这一点很重要?

    好吧,在MyApi2项目中,您引用了MyInfra项目,但是实际上并没有以任何方式使用它。这意味着程序集将不会被CLR加载,因此MediatR将无法在App Domain当前加载的程序集中找到它。结果,您的IRequestHandler将不会被注册(该项目中也不会注册任何其他MediatR基本类型)。

    解决此问题的方法是确保在对AddMediatR()的调用之前,将包含希望注册到MediatR容器中的类型的程序集加载到中。

    您可以执行以下任一操作:
  • blog post您引用的程序集
  • MyInfra项目
  • 引用MyApi2项目中的类型/函数

    后一个选项是最典型的选项,因为您通常会在要调用的引用程序集中拥有一些功能(而不是仅具有包含类型的程序集)。

    无论使用哪种选择,请确保在添加MediatR之前都已执行此操作。否则,您将遇到相同的问题。

    关于c# - 当实体位于不同的项目中时,Mediatr为什么不解析方法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55337259/

    10-12 14:53