我将如何解决第 3 层或第 4 层上的接口依赖关系
How will i resolve Dependency of interfaces which is on 3rd or 4rth layer
我正在 Dotnet Core 3.1
中创建架构。
我创建了图层
API
-> 控制器
-> 服务接口。 (这个会被Controller Layer用到)
-> 服务实施
-> 数据接口。 (这将被服务实现层作为依赖使用)
->数据实现
我不想将我的数据实现暴露给控制器层,但它必须在服务实现层的构造函数中使用。
问题是:
如何解析数据实现类?
以及如何在 IServiceCollection 中注册这些 类?
您可以通过以下方式做到这一点:
- 为每一层定义单独的项目。
- 根据需要设置层之间的依赖关系。
- 模型映射应该在
Service Layer
而不是在Controller层(通常应该在Controller层,但在您的场景中不适用)。
- 在您的
Service Layer
中安装 Microsoft.Extensions.DependencyInjection
NuGet
- 为
Service Layer
中的 DependencyInjection
定义扩展方法。
- 调用
Startup.cs
中的扩展方法
我准备了一个例子来解释答案。
示例:
具有依赖关系的解决方案框架:
示例产品端点接口和 classes 解决方案分布
端点服务的依赖注入
控制器Class代码:
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;
}
}
}
IProductService
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; }
}
}
依赖注入扩展Class
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>();
}
}
}
启动class
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();
});
}
}
}
示例源码我已经上传到GitHubhttps://github.com/ualehosaini/LayeredArchitecturePreparedToAnswerForAWhosebugQuestion。您可以将它用于您的项目,您可以 define/add 您需要的任何组件。
我正在 Dotnet Core 3.1
中创建架构。
我创建了图层
API
-> 控制器
-> 服务接口。 (这个会被Controller Layer用到)
-> 服务实施
-> 数据接口。 (这将被服务实现层作为依赖使用)
->数据实现
我不想将我的数据实现暴露给控制器层,但它必须在服务实现层的构造函数中使用。
问题是:
如何解析数据实现类?
以及如何在 IServiceCollection 中注册这些 类?
您可以通过以下方式做到这一点:
- 为每一层定义单独的项目。
- 根据需要设置层之间的依赖关系。
- 模型映射应该在
Service Layer
而不是在Controller层(通常应该在Controller层,但在您的场景中不适用)。 - 在您的
Service Layer
中安装 - 为
Service Layer
中的DependencyInjection
定义扩展方法。 - 调用
Startup.cs
中的扩展方法
Microsoft.Extensions.DependencyInjection
NuGet
我准备了一个例子来解释答案。
示例:
具有依赖关系的解决方案框架:
示例产品端点接口和 classes 解决方案分布
端点服务的依赖注入
控制器Class代码:
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;
}
}
}
IProductService
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; }
}
}
依赖注入扩展Class
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>();
}
}
}
启动class
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();
});
}
}
}
示例源码我已经上传到GitHubhttps://github.com/ualehosaini/LayeredArchitecturePreparedToAnswerForAWhosebugQuestion。您可以将它用于您的项目,您可以 define/add 您需要的任何组件。