当实体在不同的项目中时,Mediatr为什么不解析方法?

时间:2019-03-25 11:55:31

标签: c# asp.net-core mediatr

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

我收到此错误:

  

找不到用于类型请求的处理程序   MediatR.IRequestHandler`2 [MyBiz.GetTokenModelRequest,MyBiz.TokenModel]。   在容器中注册您的处理程序。查看GitHub中的示例   例如。

我在项目中使用了这种结构,并显示了它的工作位置和不工作的位置:

Project structure represented as a tree view

为进一步说明,代码如下:

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移动到MyApi,{strong> _streaming_confusion_matrix可以正常工作,但是我应该可以将其作为参考项目,对吧?

1 个答案:

答案 0 :(得分:3)

AddMediatR文件中的startup.cs的调用会做很多事情来初始化MediatR。

它执行的操作之一是在App Domain中扫描当前加载的程序集。之后,它将扫描这些程序集以查找从MediatR基本类型(IRequestHandlerINotificationHandlerIRequestPreProcessorIRequestPostProcessor)继承的每个类,然后注册它们以供MediatR使用。

记住这一点,重要的是要了解.NET CLR如何加载引用的程序集。里克·斯特拉尔(Rick Strahl)在这里有一个非常有趣的blog post,其中有详细介绍,但在这里我将用引号进行总结:

  简而言之,引用的程序集不会立即加载-会根据需要即时加载。因此,无论您是在顶级项目中拥有程序集引用,还是从属程序集,通常都根据需要加载,除非由用户代码明确加载。依赖程序集也是如此。

为什么这很重要?

好吧,在您的MyApi2项目中,您引用了MyInfra项目,但实际上并未以任何方式使用它。这意味着程序集将不会被CLR加载,因此MediatR将无法在App Domain当前加载的程序集中找到它。因此,您的IRequestHandler将不会被注册。

要解决此问题,您有几种选择,我在下面列举几个:

您可以manually load在被引用的程序集{strong>之前,在您的AddMediatR文件中调用startup.cs

您可以在MyInfra文件中调用AddMediatR之前调用startup.cs项目中的某种功能。

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