具有基类<T>的 Scrutor 依赖注入



我正在尝试配置检查器,以便我可以通过IRepository<T>,然后将解析为继承BaseRepository<T> : IRepositroy<T>的具体UserRepository

这是我的控制器

[Route("api/[controller]")]
[ApiController]
public class GetUsersController : ControllerBase
{
private readonly IMapper _mapper;
private IRepository<User> _repository;
public GetUsersController(IRepository<User> repository, IMapper mapper)
{
_mapper = mapper;
_repository = repository;
}
[HttpGet]
public ActionResult<IEnumerable<UserReadDto>> GetUsers()
{
var userItems = _repository.GetAll();
return Ok(_mapper.Map<IEnumerable<UserReadDto>>(userItems));
}

My Generic Interface

public interface IRepository<T> where T : class
{
bool SaveChanges();
IEnumerable<T> GetAll();
T GetById(int id);
void Create(T entity);
void Remove(int id);
}
使用泛型的具体基类
public class BaseRepository<T> : IRepository<T> where T : Entity
{
private AppDbContext _context;
private readonly DbSet<T> dbSet;
public BaseRepository(AppDbContext context)
{
_context = context;
dbSet = context.Set<T>();
}
public bool SaveChanges() => _context.SaveChanges() > 0;
public IEnumerable<T> GetAll() => _context.Set<T>().ToList();
public T GetById(int id) =>
_context.Set<T>().FirstOrDefault(i => i.Id == id);
public void Create(T entity) => _context.Set<T>().Add(entity);
public void Remove(int id) => _context.Set<T>().Remove(GetById(id));
}

我将在其中添加用户特定逻辑的具体用户存储库

public class UserRepository : BaseRepository<User>
{
public UserRepository(AppDbContext context) : base(context)
{
}
}

我的基本实体传递到T的基本存储库

public class Entity
{
[Key] public int Id { get; set; }
[Required] public string Name { get; set; }
}

继承自Entity的用户实体

public class User : Entity
{
[Required] public string Role { get; set; }
[Required] public string Email { get; set; }
}

我的程序。cs,我试图使用监控器的DI

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
builder.Services.Scan(
scan =>
scan.FromCallingAssembly()
.AddClasses(classes => classes.AssignableTo(typeof(IRepository<>)))
.AsImplementedInterfaces());
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();

我已经尝试在program .cs内部使用检查器扫描,但得到以下错误:

系统。InvalidOperationException:无法解析类型'Account.Service.Data.Repository.IRepository '的服务。当试图激活'Account.Service.Api.Controllers.Users.GetUsersController'时,

at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
at lambda_method3(Closure, IServiceProvider, Object[])
at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass6_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

值得一提的是,我在三个不同的项目中都有这些。

控制器位于API项目中。用户和实体在一个核心项目中。Repository类位于数据项目中。

当我尝试使用检查器时,我遇到了类似的问题。通过调试AddClasses方法中的lambda表达式,我发现我没有扫描所需的所有程序集。我想你这里也有同样的问题。您正在扫描执行程序集,它只是应用程序的启动项目。相反,您需要添加包含存储库的数据项目的程序集。

builder.Services.Scan(scan =>
scan.FromAssemblyOf<IDataAssemblyMarker>()
.AddClasses(classes => classes.AssignableTo(typeof(IRepository<>)))
.AsImplementedInterfaces());

其中IDataAssemblyMarker是数据项目中的接口。您还可以在数据项目中使用任何其他类,但我建议为此创建一个空接口,以避免在将来使其他开发人员或您自己感到困惑。然后,你也可以添加一个描述到接口,并解释你为什么使用它。

/// <summary>
/// This is an assembly marker used for scanning
/// the data projects assembly for dependency injection
/// </summary>
public interface IDataAssemblyMarker
{
}

在您提供的代码中,也没有注入AppDbContext,因此无法解析存储库。当您使用实体框架(核心)时,您可以在程序集扫描之前简单地执行此操作。

builder.Services.AddDbContext()

查看微软文档了解更多细节。

有了这两个补丁,你的问题就解决了。然而,你也应该记住,默认情况下,. asimplementtedinterfaces()将你的存储库作为Singleton注入。您可能希望使用作用域或瞬态。如欲了解更多详情,请参阅此处、此处或此处。

最新更新