注入 IRequestHandler 时出现错误
System.AggregateException:'某些服务无法构建(验证服务描述符时出错'ServiceType:MediatR.IRequestHandler
2[TabpediaFin.Handler.UnitMeasures.UnitMeasureList+Query,System.Collections.Generic.IEnumerable
1[TabpediaFin.Dto.UnitMeasureDto]]生命周期:瞬态实现类型:TabpediaFin.Handler.UnitMeasures .UnitMeasureList+QueryHandler':尝试激活“TabpediaFin.Handler.UnitMeasures.UnitMeasureList+QueryHandler”时无法解析类型“System.Data.IDbConnection”的服务。)'
DbManager.cs
using Npgsql;
namespace TabpediaFin.Infrastructure.Data;
public class DbManager
{
private readonly string _connectionString;
public DbManager(IConfiguration config)
{
_connectionString = config.GetConnectionString("DefaultConnection") ?? string.Empty;
}
public string ConnectionString => _connectionString;
public IDbConnection CreateConnection()
{
IDbConnection cn = new NpgsqlConnection(_connectionString);
DefaultTypeMap.MatchNamesWithUnderscores = true;
// SimpleCRUD.SetDialect(SimpleCRUD.Dialect.PostgreSQL);
return cn;
}
}
程序.cs
using FluentValidation.AspNetCore;
using Serilog;
using Serilog.Sinks.SystemConsole.Themes;
using System.Reflection;
using TabpediaFin.Infrastructure.Data;
using MediatR;
using TabpediaFin.Infrastructure.Validation;
using TabpediaFin.Infrastructure;
using Microsoft.AspNetCore.Builder;
using TabpediaFin.Infrastructure.OpenApi;
using Microsoft.EntityFrameworkCore.Migrations.Internal;
using TabpediaFin.Infrastructure.Migrator;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Configuration;
using Npgsql;
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.Enrich.FromLogContext()
.WriteTo.Console(
outputTemplate:
"[{Timestamp:HH:mm:ss} {Level:u3}] {SourceContext} {Message:lj}{NewLine}{Exception}",
theme: AnsiConsoleTheme.Code)
.CreateBootstrapLogger();
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog();
builder.Services.AddMediatR(Assembly.GetExecutingAssembly());
builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationPipelineBehavior<,>));
builder.Services.AddDbMigrator();
builder.Services.AddDbContext<FinContext>();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.RegisterSwagger("Tabpedia Finance", "v1");
builder.Services.AddControllers(options =>
{
options.Filters.Add<ValidateModelFilter>();
})
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressModelStateInvalidFilter = true;
})
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
});
builder.Services.AddFluentValidationAutoValidation();
builder.Services.AddCors();
builder.Services.RegisterSettings(builder.Configuration);
builder.Services.RegisterServices();
builder.Services.RegisterRepositories();
//builder.Services.AddScoped<IDbConnection>(db => new NpgsqlConnection(Configuration.GetConnectionString("AppConnectionString")));
builder.Services.AddJwt();
var app = builder.Build();
app.UseMiddlewares();
// Configure the HTTP request pipeline.
// if (app.Environment.IsDevelopment())
// {
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Tabpedia Finance v1"));
// }
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(
builder =>
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
.WithExposedHeaders("Token-Expired"));
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.MapControllers();
using (var scope = app.Services.CreateScope())
{
TabpediaFin.Infrastructure.Migrator.Startup.UpdateDatabase(scope.ServiceProvider);
}
app.Run();
UnitMeasureList.cs
using Microsoft.EntityFrameworkCore;
namespace TabpediaFin.Handler.UnitMeasures
{
public class UnitMeasureList
{
public class Query : IRequest<IEnumerable<UnitMeasureDto>>
{ }
public class QueryHandler : IRequestHandler<Query, IEnumerable<UnitMeasureDto>>
{
private readonly IDbConnection _dbConnection;
private readonly ICurrentUser _currentUser;
public QueryHandler(
IDbConnection connection,
ICurrentUser currentUser)
{
_dbConnection = connection;
_currentUser = currentUser;
}
public async Task<IEnumerable<UnitMeasureDto>> Handle(Query req, CancellationToken cancellationToken)
{
string sql = $@"SELECT
um.*, at.Id, au.Id
FROM UnitMeasure um
INNER JOIN AppTenant at ON at.Id = um.Id
INNER JOIN AppUser au ON au.Id = um.Id ";
var unitMeasure = await _dbConnection.QueryAsync<UnitMeasureDto>(sql, new {
userName = _currentUser.Username
});
return unitMeasure.ToList();
}
}
}
}
UnitMeasureDto.cs
namespace TabpediaFin.Dto
{
public class UnitMeasureDto
{
protected UnitMeasureDto(
int id
,int tenantId
,string name
,string description
,int createdUid
,DateTime createdUtc
,int updatedUid
,DateTime updatedUtc
)
{
Id = id;
TenantId = tenantId;
Name = name;
Description = description;
CreatedUid = createdUid;
CreatedUtc = createdUtc;
UpdatedUid = updatedUid;
UpdatedUtc = updatedUtc;
}
public int Id { get; set; }
public int TenantId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int CreatedUid { get; set; }
public DateTime CreatedUtc { get; set; }
public int UpdatedUid { get; set; }
public DateTime UpdatedUtc { get; set; }
}
}
UnitMeasuresController.cs
namespace TabpediaFin.Handler.UnitMeasures
{
[Route("api/[controller]")]
[ApiController]
public class UnitMeasuresController : ControllerBase
{
private readonly IMediator _mediator;
public UnitMeasuresController(
IMediator mediator)
{
_mediator = mediator;
}
[HttpGet]
public async Task<IEnumerable<UnitMeasureDto>> Get() => await _mediator.Send(new UnitMeasureList.Query());
}
}
在Program.cs中 我改变了这一行
//builder.Services.AddScoped<IDbConnection>(db => new NpgsqlConnection(Configuration.GetConnectionString("AppConnectionString")));
到此
builder.Services.AddScoped<IDbConnection>(db => new NpgsqlConnection(builder.Configuration.GetConnectionString("AppConnectionString")));
您从未在容器(ServiceCollection)中注册IDbConnection,这就是您收到错误的原因
删除代码:
private readonly IDbConnection _dbConnection;
以及构造函数中的相关代码
并在
public async Task<IEnumerable<UnitMeasureDto>> Handle(Query req, CancellationToken cancellationToken)
中创建 DbManager 的实例
您也可以尝试将 DbManager 注入到容器中:
builder.Services.AddTrainsident<DbManager>()
这是一个带有注释的很好的例子 使用 AnnationServiceBilder.Annotations.Transient_Services;
[TransientService]
public class MyTransientService
{
// Implementation...
}
https://github.com/genryianchev/AnnationServiceBilder/tree/main