【问题标题】:System.InvalidOperationException: Unable to resolve service for type - Dependency InjectionSystem.InvalidOperationException:无法解析类型的服务 - 依赖注入
【发布时间】:2020-12-17 07:35:55
【问题描述】:

我正在开发一个 Web 应用程序 - 托管在 ASP.NET 上的 Blazor WebAssembly。我正在尝试开始从数据库中获取价值(使用实体框架)。我在我的解决方案中使用 Repository 和 UnitOfWork 模式。 所以,我遇到了这个错误:

An unhandled exception has occurred while executing the request.
      System.InvalidOperationException: Unable to resolve service for type 'ReportApp.Core.Services.TaskService' while attempting to activate 'ReportApp.Server.Controllers.TaskController'.
         at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
         at lambda_method8(Closure , IServiceProvider , Object[] )
         at Microsoft.AspNetCore.Mvc.Controllers.ControllerActivatorProvider.<>c__DisplayClass4_0.<CreateActivator>b__0(ControllerContext controllerContext)
         at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_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.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
      --- End of stack trace from previous location ---
         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.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext context)
         at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext context)
         at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

我的项目结构如下:

DbContext类:

public class ReportAppContext : DbContext
{
    public DbSet<TaskEntity> Tasks { get; set; }
        public DbSet<ReportEntity> Reports { get; set; }
        public DbSet<EmployeeEntity> Employees { get; set; }
        
        public ReportAppContext()
        {
        }

        public ReportAppContext(DbContextOptions<ReportAppContext> options) : base(options)
        {
        }
}

Repository接口:

public interface ITaskRepository : IGenericRepository<TaskEntity>
    {
    }

public interface IGenericRepository<TEntity> where TEntity : class
    {
        Task<TEntity> GetByIdAsync(Int32 id);
        Task InsertAsync(TEntity entity);
        Task UpdateAsync(TEntity entity);
        Task DeleteAsync(Int32 id);
        Task<IEnumerable<TEntity>> GetAllAsync();
        Task SaveAsync();
    }

public class TaskRepository : ITaskRepository
    {
        private readonly ReportAppContext _context;

        public TaskRepository(ReportAppContext context)
        {
            _context = context;
        }

然后我有UnitOfWork 模式:

public class UnitOfWork : ReportAppContext, IUnitOfWork
    {
        private readonly ITaskRepository _taskRepository;

和服务器上的控制器:

[Route("api/[controller]")]
    [ApiController]
    public class TaskController : ControllerBase
    {
        private readonly TaskService _taskService;

        public TaskController(TaskService taskService)
        {
            _taskService = taskService;
        }

        [HttpGet("get-all")]
        public async Task<ActionResult<List<TaskDto>>> GetAllTasksAsync()
        {
            var result = await _taskService.GetAllAsync();
            return Ok(result);
        }

最后,Startup类配置:

public void ConfigureServices(IServiceCollection services)
        {
            var connection = Configuration.GetConnectionString("DefaultConnection");
            services.AddDbContext<ReportAppContext>(options => options.UseSqlServer(connection));
            services.AddCors();

            services.AddServerSideBlazor().AddCircuitOptions(options => { options.DetailedErrors = true; });
            services.AddControllersWithViews();
            services.AddRazorPages();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseWebAssemblyDebugging();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseBlazorFrameworkFiles();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
                endpoints.MapControllers();
                endpoints.MapFallbackToFile("index.html");
            });
        }

我已经尝试添加这个:

services.AddTransient<ITaskRepository, TaskRepository>();

AddScoped一样,但它没有改变任何东西......

【问题讨论】:

    标签: c# blazor blazor-server-side blazor-webassembly asp.net-blazor


    【解决方案1】:

    但是在您的TaskController 中,您注入的是TaskService,而不是TaskRepository。我认为您还需要注册 TaskService(我假设 TaskService 使用 TaskRepository。两者都可以注册为 Scoped)。

    services.AddTransient<ITaskRepository, TaskRepository>(); OR
    services.AddScoped<ITaskRepository, TaskRepository>();
    services.AddTransient<TaskService>(); OR
    services.AddScoped<TaskService>(); 
    

    作用域和瞬态之间的区别在于,当您将服务注册为瞬态时,每次解析时都会返回一个新实例,而作用域会在作用域内返回相同的实例。

    【讨论】:

    • 我添加了:services.AddTransient&lt;ITaskRepository, TaskRepository&gt;(); services.AddTransient&lt;TaskService&gt;();,现在它说:System.AggregateException: "Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: ReportApp.Core.Services.TaskService Lifetime: Transient ImplementationType: ReportApp.Core.Services.TaskService': Unable to resolve service for type 'ReportApp.DAL.Tools.UnitOfWork' while attempting to activate 'ReportApp.Core.Services.TaskService'.)"
    • 我认为 UnitOfWork 不应该从您的数据库上下文继承。只需将游览上下文注入 UnitOf Work
    【解决方案2】:

    错误告诉你TaskService没有注册,但你的Controller需要它作为注入服务。

    在 ConfigureServices 中,尝试如下操作:

    services.AddScoped<TaskService>(sp => {
        // Build your Context Options
        DbContextOptionsBuilder<ReportAppContext> optsBuilder = new DbContextOptionsBuilder<ReportAppContext>();
        optsBuilder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
        // Build your context (using the options from the builder)
        ReportAppContext ctx = new ReportAppContext(optsBuilder.options);
        // Build your unit of work (and pass in the context)
        UnitOfWork uow = new UnitOfWork(ctx);
        // Build your service (and pass in the unit of work)
        TaskService svc = new TaskService(uow)
        // Return your Svc
        return svc;
    });
    

    然后,您的控制器将收到一个完全配置的 TaskService,可供使用。

    如果你愿意,你可以将每个项目依次放入 DI 容器中,但是 UOW、Repository 和 Context 不需要在 TaskService 之外访问,所以有点浪费时间。

    只需像上面一样创建已配置的TaskService,这就是DI容器需要注入的全部内容。

    【讨论】:

      猜你喜欢
      • 2021-10-29
      • 1970-01-01
      • 2019-07-02
      • 1970-01-01
      • 1970-01-01
      • 2020-04-06
      • 2019-12-20
      • 1970-01-01
      • 2017-04-15
      相关资源
      最近更新 更多