I am trying to configure scrutor so that I can pass in an IRepository<T>
which then will resolve to a concreate UserRepository
that inherits BaseRepository<T> : IRepositroy<T>
This is my controller
[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);
}
The concrete base class using generics
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));
}
The concrete user repository where I will add user specific logic
public class UserRepository : BaseRepository<User>
{
public UserRepository(AppDbContext context) : base(context)
{
}
}
my base entity passed to the base repository for T
public class Entity
{
[Key] public int Id { get; set; }
[Required] public string Name { get; set; }
}
The user entity which inherits from Entity
public class User : Entity
{
[Required] public string Role { get; set; }
[Required] public string Email { get; set; }
}
My Program.cs where I am trying to use Scrutor for the 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();
I have tried to use Scrutor's scan inside of progam.cs but get the following error:
System.InvalidOperationException: Unable to resolve service for type 'Account.Service.Data.Repository.IRepository`1[Account.Service.Core.Entities.User]' while attempting to activate '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)
It may be worth mentioning that I have these across three separate projects.
The controllers are in an API project. The User and Entity are in a Core project. The Repository classes are in a data project.