【问题标题】:How will i resolve Dependency of interfaces which is on 3rd or 4rth layer我将如何解决第 3 层或第 4 层接口的依赖关系
【发布时间】:2020-12-13 12:36:47
【问题描述】:

我正在Dotnet Core 3.1 中创建架构。

我已经创建了图层

API

-> 控制器

-> 服务接口。 (这将被控制器层使用)

-> 服务实现

-> 数据接口。 (这将被服务实现层用作依赖项)

-> 数据实现

我不想将我的数据实现暴露给控制器层,但它必须在服务实现层的构造函数中使用。

问题是:

如何解析数据实现类?

以及如何在 IServiceCollection 中注册这些类?

【问题讨论】:

  • 显示一些代码以提供更好的示例来说明您所指的内容。
  • 正如 Nksoi 所说,请提供代码示例以帮助说明您当前的设计。如果不知道每个层当前具有哪些依赖项,则无法推荐解决方案。

标签: c# .net-core dependency-injection software-design n-tier-architecture


【解决方案1】:

你可以这样做:

  1. 为每一层定义单独的项目。
  2. 根据需要设置层之间的依赖关系。
  3. 模型映射应该在Service Layer而不是在控制器层(通常应该在控制器层,但在您的场景中不适用)。
  4. 在您的Service Layer 中安装Microsoft.Extensions.DependencyInjection NuGet
  5. Service Layer 中定义DependencyInjection 的扩展方法。
  6. 调用Startup.cs中的扩展方法

我准备了一个例子来解释答案。

例子:

具有依赖关系的解决方案骨架:

解决方案上的示例产品端点接口和类分布

端点服务的依赖注入

控制器类代码:

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using TestProj.AppServices.Interfaces;

namespace TestProj.Api.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class ProductsController : ControllerBase
    {
        private readonly ILogger<ProductsController> _logger;
        private readonly IProductService _service;

        public ProductsController(ILogger<ProductsController> logger,
                                  IProductService service)
        {
            _logger = logger;
            _service = service;
        }

        [HttpGet("{id=1}")] //Set default value for example only, it should be [HttpGet("{id}")]
        public IActionResult Get(int id)
        {
            return Ok(_service.GetById(id));
        }
    }
}

产品服务

    using TestProj.AppServices.Interfaces;
    using TestProj.AppServices.Models;
    using TestProj.Data.Interfaces;
    
    namespace TestProj.AppServices.AppServices
    {
        public class ProductService : IProductService
        {
            private readonly IProductRepository _repository;
    
            public ProductService(IProductRepository repository)
            {
                _repository = repository;
            }
            public Product GetById(int id)
            {
                //Subject code here
    
                //Dummy code:
                var productFromDataLayer = _repository.GetById(id);
    
                //Mapping (You can use AutoMapper NuGet)
                var product = new Product
                {
                    Id = productFromDataLayer.Id,
                    Name = productFromDataLayer.Name
                };
    
                return product;
            }
        }
    }

产品服务

using TestProj.AppServices.Models;

namespace TestProj.AppServices.Interfaces
{
    public interface IProductService
    {
        Product GetById(int id);
    }
}

产品服务层模型

namespace TestProj.AppServices.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}

产品库

using TestProj.Data.Interfaces;
using TestProj.Data.Model;

namespace TestProj.Data.Data
{
    public class ProductRepository : IProductRepository
    {
        public Product GetById(int id)
        {
            //Subject code here

            //Dummy code:
            var product = new Product
            {
                Id = 1,
                Name = "Product 1"
            };

            return product;
        }
    }
}

IProductRepository

using TestProj.Data.Model;

namespace TestProj.Data.Interfaces
{
    public interface IProductRepository
    {
        Product GetById(int id);
    }
}

数据层产品模型(实体)

namespace TestProj.Data.Model
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}

依赖注入扩展类

using Microsoft.Extensions.DependencyInjection;
using TestProj.AppServices.AppServices;
using TestProj.AppServices.Interfaces;
using TestProj.Data.Data;
using TestProj.Data.Interfaces;

namespace TestProj.AppServices.Others
{
    public static class DependencyInjection
    {
        public static void AddProjectServicesAndRepositoresDependencyInjection(this IServiceCollection services)
        {

            //Services
            services.AddTransient<IProductService, ProductService>();

            //Data
            services.AddTransient<IProductRepository, ProductRepository>();
        }
    }
}

启动类

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using TestProj.AppServices.Others;

namespace TestProj.Api
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

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

            services.AddControllers();
        }

        // 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.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

我已将示例的源代码上传到 GitHub https://github.com/ualehosaini/LayeredArchitecturePreparedToAnswerForAStackOverflowQuestion 。您可以将它用于您的项目,您可以定义/添加您需要的任何组件。

【讨论】:

  • 谢谢先生。您为我的问题找到了正确的方案。您是否建议创建新项目来管理所有层的依赖关系?
  • 不用担心 :),是的,您可以将项目想象为防火墙,并将依赖项定义为您只允许的。按照示例项目的步骤操作。
猜你喜欢
  • 1970-01-01
  • 2020-01-17
  • 1970-01-01
  • 2015-01-09
  • 1970-01-01
  • 2023-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多