【问题标题】:IDatabaseService dependency injection failed?IDatabaseService 依赖注入失败?
【发布时间】:2017-09-24 00:54:19
【问题描述】:

我正在使用以域为中心的架构创建 asp.net 应用程序。由于依赖注入无法解析 Demeter.Application.Events.Queries.QueryEvent.GetEventsListQuery 中的 Demeter.Application.Interfaces.IDatabaseService,我在应用程序层遇到问题@ .有人可以帮我修复依赖注入吗?

System.InvalidOperationException:无法解析服务类型 'Demeter.Application.Interfaces.IDatabaseService' 尝试 启用 'Demeter.Application.Events.Queries.QueryEvent.GetEventsListQuery'。

namespace Demeter.Application.Events.Queries.QueryEvent
{
    using System.Collections.Generic;
    using Commands.CreateEvent;
    using Demeter.Application.Interfaces;
    using AutoMapper;
    using Domain;


    public class GetEventsListQuery : IGetEventsListQuery
    {
        public List<ListEventModel> Execute()
        {
            var events = this.databaseService.SelectEventsForList();

            //// Use AutoMapper to convert events (IEnumerable<Event>) to (List<ListEventModel>)
            //IMapper mapperConfig = this.mapperConfig.CreateMapper();

            //return Mapper.Map<IEnumerable<Event>, List<ListEventModel>>(events);
            return null;
        }

        public GetEventsListQuery(IDatabaseService databaseService)
        {
            this.databaseService = databaseService;
            //TO-DO: Move this to mapper congigfration function 
            //this.mapperConfig = new MapperConfiguration(cfg => {
            //    cfg.CreateMap<Event, ListEventModel>();
            //});
        }

        private readonly IDatabaseService databaseService;
        private readonly MapperConfiguration mapperConfig;

    }
}

namespace Demeter.Application.Interfaces
{
    using System.Collections.Generic;
    using Domain;

    public interface IDatabaseService
    {
        void InsertEvent(Event @event);
        void UpdateEvent(Event @event);
        void DeleteEvent(long recordId);
        IEnumerable<Event> SelectEventsForList();
    }
}

startup.cs 表单服务

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();

        this.Configuration = builder.Build();


    }

    public IConfigurationRoot Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {

        // Add framework services.
        services.AddScoped(provider =>
        {
            var connectionString = new SqlConnection(Configuration["ConnectionStrings:DevConnection"]);
            return connectionString;
        });
        // Register the Swagger generator, defining one or more Swagger documents
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
        });
        services.AddMvc();

        services.AddTransient<IGetEventsListQuery, GetEventsListQuery>();


    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(this.Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();


        app.UseMvc();

        // Enable middleware to serve generated Swagger as a JSON endpoint.
        app.UseSwagger();

        // Enable middleware to serve swagger-ui (HTML, JS, CSS etc.), specifying the Swagger JSON endpoint.
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
        });
    }
}

}

这是IDatabaseService在Persistance中的实现

namespace Demeter.Persistance.Services
{
    using System;
    using System.Collections.Generic;
    using Application.Interfaces;
    using Domain;
    using System.Data;
    using System.Data.SqlClient;
    using Dapper;

    public class DatabaseService : IDatabaseService
    {
        public void InsertEvent(Event @event)
        {
            throw new NotImplementedException();
        }

        public void UpdateEvent(Event @event)
        {
            throw new NotImplementedException();
        }

        public void DeleteEvent(long recordId)
        {
            throw new NotImplementedException();
        }

        public IEnumerable<Event> SelectEventsForList()
        {
            using (IDbConnection dbConnection = Connection)
            {      
                return dbConnection.Query<Event>("SELECT * FROM Event");
            }

        }

        public IDbConnection Connection
        {
            get
            {
                return new SqlConnection(connectionString);
            }
        }

        public DatabaseService(string connectionString)
        {
            this.connectionString = connectionString;
        }

        private readonly string connectionString;

    }
}

【问题讨论】:

  • 你在你的创业公司注册IDatabaseService了吗?
  • 你的 DI 初始化代码在哪里?正如@DavidG 所说,您是否在某处为IDatabaseService 注册了具体类型?
  • 我不这么认为。这是我第一次使用 asp.net CORE 了解以域为中心的架构。请问如何在你的startup中注册IDatabaseService?
  • @NinjaDeveloper 能给我们展示一下IDatabaseService的具体实现吗?
  • @FedericoDipuma 我添加了实现 IDatabaseService

标签: c# dependency-injection asp.net-core domain-driven-design


【解决方案1】:

您需要将IDatabaseService注册到ASP.NET Core的依赖注入引擎。

这是在 Startup.cs 文件的 ConfigureServices 方法中完成的。

通过查看您的DatabaseService 实现,它似乎依赖于连接字符串,但在您的ConfigureServices 方法中,您已经提供了完整的SqlConnection

要使用 DI 使一切正常工作,您需要进行一些更改,直接在构造函数中使用连接:

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddScoped<IDbConnection>(provider => new SqlConnection(Configuration["ConnectionStrings:DevConnection"]));
    // Register the Swagger generator, defining one or more Swagger documents
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
    });
    services.AddMvc();

    services.AddTransient<IGetEventsListQuery, GetEventsListQuery>();

    // Register your database service
    services.AddScoped<IDatabaseService, DatabaseService>();
}

public class DatabaseService : IDatabaseService
{
    public void InsertEvent(Event @event)
    {
        throw new NotImplementedException();
    }

    public void UpdateEvent(Event @event)
    {
        throw new NotImplementedException();
    }

    public void DeleteEvent(long recordId)
    {
        throw new NotImplementedException();
    }

    public IEnumerable<Event> SelectEventsForList()
    {
        _dbConnection.Query<Event>("SELECT * FROM Event");
    }

    public DatabaseService(IDbConnection dbConnection)
    {
        _dbConnection = dbConnection;
    }

    private readonly IDbConnection _dbConnection;

}

在示例中,我将注册添加为“作用域”,因为它似乎直接依赖于数据库连接(也声明为作用域)。

这也将确保为每个请求创建和使用一个 IDatabaseService

【讨论】:

    【解决方案2】:

    您还没有为IDatabaseService 接口注册具体类型。像这样添加一行:

    services.AddTransient<IDatabaseService, DatabaseService>();
    

    否则,DI 框架不知道将什么注入到 GetEventsListQuery 类的构造函数中。

    我建议阅读 the docs,了解如何在 .Net Core 中完成依赖注入。

    【讨论】:

      猜你喜欢
      • 2017-09-16
      • 2012-08-13
      • 1970-01-01
      • 1970-01-01
      • 2019-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多