Я изучаю ASP .NET Core и сегодня наткнулся на что-то. У меня есть класс User
, который наследует IdentityUser
и добавляет некоторые настраиваемые поля, такие как имя, фамилия и т. Д. *
Класс User
дополнительно расширяется другими типами пользователей, которые добавляют не более одного или двух дополнительных полей. Я решил пойти по этому пути, так как не нужно было повторять один и тот же код в 4 местах.
Я определил UserRepository
, который реализует интерфейс IUserRepository<TEntity> where TEntity : User
. Всякий раз, когда я пытаюсь получить доступ к Index
, я получаю исключение, например:
InvalidOperationException: No service for type 'Microsoft.AspNetCore.Identity.UserManager`1[HM.models.users.Medic]' has been registered.
Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService<T>(IServiceProvider provider)
HM.repositories.UserRepository<TEntity>..ctor(ApplicationDbContext context, IServiceProvider serviceProvider, string role) in UserRepository.cs
+
_userManager = serviceProvider.GetRequiredService<UserManager<TEntity>>();
HM.repositories.MedicRepository..ctor(ApplicationDbContext context, IServiceProvider serviceProvider) in MedicRepository.cs
+
public MedicRepository(ApplicationDbContext context, IServiceProvider serviceProvider) : base(context, serviceProvider, _role) { }
HM.persistence.UnitOfWork..ctor(ApplicationDbContext context, IServiceProvider _serviceProvider) in UnitOfWork.cs
+
Medics = new MedicRepository(_context, _serviceProvider);
app.Controllers.MedicController.Index() in MedicController.cs
+
using (var unitOfWork = new UnitOfWork(_context, _serviceProvider))
Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)
System.Threading.Tasks.ValueTask<TResult>.get_Result()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Вот некоторые фрагменты кода:
MedicController
// GET: Medic
public async Task<IActionResult> Index()
{
using (var unitOfWork = new UnitOfWork(_context,_serviceProvider))
{
return View(await unitOfWork.Medics.GetAll());
}
}
UserRepository
и IUserRepository
:
public interface IUserRepository<TEntity> where TEntity : User
{
Task Add(TEntity user, string password);
Task Remove(TEntity user);
Task Update(TEntity user);
Task<IEnumerable<TEntity>> GetAll();
Task<TEntity> GetById(string id);
Task<bool> Any(Func<TEntity, bool> predicate);
}
public class UserRepository<TEntity> : IUserRepository<TEntity> where TEntity : User
{
private readonly string _role;
private readonly UserManager<TEntity> _userManager;
public UserRepository(ApplicationDbContext context, IServiceProvider serviceProvider, string role)
{
_role = role;
_userManager = serviceProvider.GetRequiredService<UserManager<TEntity>>();
}
public async Task<IEnumerable<TEntity>> GetAll()
{
return await _userManager.GetUsersInRoleAsync(_role);
}
}
Наконец, медик:
[Table("Medic")]
public class Medic : User
{
[DisplayName("Departments")]
public ICollection<MedicDepartment> departments { get; set; }
[DisplayName("Diagnostics")]
public ICollection<MedicDiagnostic> diagnostics { get; set; }
[PersonalData]
[DisplayName("Rank")]
[StringLength(30, MinimumLength = 3, ErrorMessage = "The rank name must be between 3 and 30 characters long!")]
public string rank { get; set; }
}
Я отладил приложение: оно выдаст это исключение на _userManager = serviceProvider.GetRequiredService<UserManager<TEntity>>();
внутри UserRepository
. Я не понимаю, почему это происходит с тех пор
Я четко сказал where TEntity : User
.
Спасибо!
Постскриптум Я удалил некоторый код и некоторые emthods, чтобы сделать этот пост более читабельным.
P.S.S: Класс MedicRepository
расширяет UserRepository
и вызывает base
и пока не содержит ничего другого. UnitOfWork
содержит все репозитории приложений и вызывает new
для каждого из них внутри своего конструктора.
P.S.S.S. Я хотел использовать шаблоны для этого хранилища, чтобы избежать приведения внутри контроллеров. Используется для возврата данных, связанных с пользователем.