E-A*_*E-A 5 c# mediatr asp.net-core
我有一个简单的项目来尝试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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
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" };
}
}
}
Run Code Online (Sandbox Code Playgroud)
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
}
}
Run Code Online (Sandbox Code Playgroud)
MyInftra-> TokenQueryHandler
namespace MyInfra
{
public class TokenQueryHandler : ITokenQueryHandler
{
public Task<TokenModel> Handle(GetTokenModelRequest request, CancellationToken cancellationToken)
{
return Task.FromResult(new TokenModel());
}
}
}
Run Code Online (Sandbox Code Playgroud)
所以,如果我MOVE TokenQueryHandler来自MyInfra于MyApi它的工作原理,但我应该能够把它引用项目,对不对?
从版本7.0.0的的MediatR.Extensions.Microsoft.DependencyInjection包,AppDomain不再被自动扫描含有MediatR基类型注册,呼叫时加载的程序集AddMediatR()的扩展方法。
实际上,该函数的无参数重载已从包中完全消除,需要用户传入程序集(或类型)进行扫描。
这使得MediatR基类型(登记IRequestHandler,INotificationHandler,IRequestPreProcessor和IRequestPostProcessor内每个引用的组件),明确地在用户的控制和判断。
因此,如果我们在假想的程序集中有一些MediatR基本类型,Assembly1并且Assembly2我们想在MediatR容器中注册:
而不是做: services.AddMediatR();
您需要执行以下操作: services.AddMediatR(typeof(Assembly1), typeof(Assembly2));
这使我的原始答案(下)对于使用此软件包的版本7(或更高版本)的任何人都是多余的,但对于使用较旧版本的用户,我将保留在这里。
注意:以下答案仅与<7.0.0的MediatR.Extensions.Microsoft.DependencyInjection程序包相关。
对文件中AddMediatR()扩展方法的调用完成了startup.cs许多初始化MediatR的操作:
IRequestHandler,INotificationHandler,IRequestPreProcessor和IRequestPostProcessor)考虑到以上几点,理解.NET CLR如何加载引用的程序集很重要。里克·斯特拉尔(Rick Strahl)有一篇非常有趣的博客文章,其中涉及细节,但在这里我将引述为总结:
简而言之,引用的程序集不会立即加载-会根据需要即时加载。因此,无论您是在顶级项目中拥有程序集引用,还是从属程序集,通常都根据需要加载,除非由用户代码明确加载。依赖程序集也是如此。
为什么要知道这一点很重要?
嗯,在您的MyApi2项目中,您引用了该MyInfra项目,但实际上并没有以任何方式使用它。这意味着程序集将不会被CLR加载,因此MediatR将无法在App Domain当前加载的程序集中找到它。结果,您IRequestHandler将不会被注册(该项目中也不会注册任何其他MediatR基本类型)。
解决此问题的方法是确保在调用之前加载包含要在MediatR容器中注册的类型的程序集AddMediatR()。
您可以执行以下任一操作:
MyInfra从MyApi2项目中引用项目中的类型/函数后一个选项是最典型的选项,因为您通常会在要调用的引用程序集中拥有某些功能(而不是仅具有包含类型的程序)。
无论使用哪种选择,请确保在添加MediatR之前都已执行此操作。否则,您将遇到相同的问题。
| 归档时间: |
|
| 查看次数: |
604 次 |
| 最近记录: |