Sal*_*des 0 c# dependency-injection mediatr asp.net-core blazor
我创建了一个应用程序程序集,并引用了 REST-Api 和 Blazor 应用程序。REST-Api 工作正常,但 Blazor 应用程序出现以下错误:
InvalidOperationException:无法从根提供程序解析“MediatR.IRequestHandler`2[Application.Customers.Queries.GetCustomersList.GetCustomersListQuery,Application.Common.Viewmodels.CustomerListVm]”,因为它需要范围服务“Application.Common.Interfaces.IWegisterDbContext”。Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.ValidateResolution(类型 serviceType、IServiceScope 范围、IServiceScope rootScope)
InvalidOperationException:为 MediatR.IRequestHandler`2[Application.Customers.Queries.GetCustomersList.GetCustomersListQuery,Application.Common.Viewmodels.CustomerListVm] 类型的请求构造处理程序时出错。向容器注册您的处理程序。有关示例,请参阅 GitHub 中的示例。MediatR.Internal.RequestHandlerBase.GetHandler(ServiceFactory工厂)
在下面的代码示例中,我放置了我的 Starup 文件,两个项目都位于同一解决方案中,引用相同的项目。我已经尝试添加授权,但这显然不起作用。我不知道问题是什么,是我遗漏了什么还是这就是 Blazor?两个程序集中的 MediatR 版本相同。
这是我从 REST-Api 启动的:
using Application;
using Application.Common.Interfaces;
using Infrastructure;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Persistence;
using WebApi.Services;
namespace Wegister.WebApi
{
public class Startup
{
public IWebHostEnvironment Environment { get; }
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration, IWebHostEnvironment environment)
{
Configuration = configuration;
Environment = environment;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddPersistence(Configuration);
services.AddInfrastructure();
services.AddApplication();
if (Environment.IsDevelopment())
{
services.AddScoped<ICurrentUserService, CurrentUserServiceDev>();
}
services.AddAuthorization(x =>
{
if (Environment.IsDevelopment())
x.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireAssertion(_ => true)
.Build();
});
services.AddControllers().AddNewtonsoftJson(options =>
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
);
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseHsts();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我在 Blazor 应用程序中的启动:
using Application;
using Application.Common.Interfaces;
using Infrastructure;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Persistence;
using WebUI.Services;
namespace WebUI
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<SessionService>();
services.AddSingleton<WorkHourService>();
services.AddSingleton<ItemService>();
services.AddSingleton<CustomerService>();
services.AddPersistence(Configuration);
services.AddInfrastructure();
services.AddApplication();
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddScoped<ICurrentUserService, CurrentUserServiceDev>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
}
}
Run Code Online (Sandbox Code Playgroud)
AddApplication依赖注入方法如下:
public static IServiceCollection AddApplication(this IServiceCollection services)
{
services.AddScoped<IRequestHandler<GetCustomersListQuery, CustomerListVm>, GetCustomersListQueryHandler>();
services.AddMediatR(Assembly.GetExecutingAssembly());
services.AddTransient<ICustomerFactory, CustomerFactory>();
return services;
}
Run Code Online (Sandbox Code Playgroud)
添加持久性:
public static IServiceCollection AddPersistence(this IServiceCollection services, IConfiguration configuration)
{
services.AddDbContext<WegisterDbContext>(options =>
options.UseSqlServer(configuration.GetConnectionString("WegisterDbConnectionString")));
services.AddScoped<IWegisterDbContext>(provider => provider.GetService<WegisterDbContext>());
return services;
}
Run Code Online (Sandbox Code Playgroud)
基础设施:
public static IServiceCollection AddInfrastructure(this IServiceCollection services)
{
services.AddTransient<IDateTime, MachineDateTime>();
services.AddTransient<INotificationService, NotificationService>();
return services;
}
Run Code Online (Sandbox Code Playgroud)
小智 5
不幸的是,“注册你的处理程序”可能有许多不同的原因(正如我自己发现的那样)。您将需要阅读 这篇关于此事的文章。当您的数据库上下文位于不同的程序集中时,我将您直接链接到对我来说是最终修复的那个。但这只是在我修复了文章中提到的其他几个问题之后才出现的问题。
总结一下:
serviceprovider不要验证 中的范围 CreateHostBuilder。(感谢莎拉·阿克巴里)Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
}).UseDefaultServiceProvider(options =>
options.ValidateScopes = false); // needed for mediatr DI
Run Code Online (Sandbox Code Playgroud)
services.AddScoped<IRepo1, Repo1>();
Run Code Online (Sandbox Code Playgroud)
var assembly = AppDomain.CurrentDomain.Load("HandlersDomain");
var assembly2 = AppDomain.CurrentDomain.Load("HandlersDomain2");
services.AddMediatR(assembly, assembly);
Run Code Online (Sandbox Code Playgroud)
遵循这个食谱,你真的应该是gtg。