我有一个简单的项目来尝试Mediatr问题。当我的API的SAME项目中的处理程序的具体类起作用时,它将起作用。但是,当我将该处理程序类带入另一个项目(并且API引用该项目的c)时,它不会解析注册表。
我收到此错误:
找不到用于类型请求的处理程序 MediatR.IRequestHandler`2 [MyBiz.GetTokenModelRequest,MyBiz.TokenModel]。 在容器中注册您的处理程序。查看GitHub中的示例 例如。
我在项目中使用了这种结构,并显示了它的工作位置和不工作的位置:
为进一步说明,代码如下:
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());
}
}
}
因此,如果我将TokenQueryHandler
从MyInfra
移动到MyApi
,{strong> _streaming_confusion_matrix
可以正常工作,但是我应该可以将其作为参考项目,对吧?>
答案 0 :(得分:3)
对AddMediatR
文件中的startup.cs
的调用会做很多事情来初始化MediatR。
它执行的操作之一是在App Domain中扫描当前加载的程序集。之后,它将扫描这些程序集以查找从MediatR基本类型(IRequestHandler
,INotificationHandler
,IRequestPreProcessor
和IRequestPostProcessor
)继承的每个类,然后注册它们以供MediatR使用。
记住这一点,重要的是要了解.NET CLR如何加载引用的程序集。里克·斯特拉尔(Rick Strahl)在这里有一个非常有趣的blog post,其中有详细介绍,但在这里我将用引号进行总结:
简而言之,引用的程序集不会立即加载-会根据需要即时加载。因此,无论您是在顶级项目中拥有程序集引用,还是从属程序集,通常都根据需要加载,除非由用户代码明确加载。依赖程序集也是如此。
为什么这很重要?
好吧,在您的MyApi2
项目中,您引用了MyInfra
项目,但实际上并未以任何方式使用它。这意味着程序集将不会被CLR加载,因此MediatR将无法在App Domain当前加载的程序集中找到它。因此,您的IRequestHandler
将不会被注册。
要解决此问题,您有几种选择,我在下面列举几个:
您可以manually load在被引用的程序集{strong>之前,在您的AddMediatR
文件中调用startup.cs
。
或
您可以在MyInfra
文件中调用AddMediatR
之前调用startup.cs
项目中的某种功能。
后一个选项是最典型的选项,因为您通常会 具有一些要调用的引用程序集中的功能(而不是仅具有保存类型的程序集)。