Я создаю архитектуру в Dotnet Core 3.1
.
Я создал слои
API
-> Контроллер
-> Сервисный интерфейс. (Это будет использоваться уровнем контроллера)
-> Реализация услуги
-> Интерфейс данных. (Это будет использоваться уровнем реализации службы в качестве зависимости)
-> Реализация данных
Я не хочу выставлять свою реализацию данных на уровень контроллера, но ее нужно использовать в конструкторе уровня реализации службы.
Вопрос в том:
Как разрешить классы реализации данных?
А как прописать эти классы в IServiceCollection?
Как сказал Нксой, пожалуйста, предоставьте примеры кода, чтобы проиллюстрировать ваш текущий дизайн. Невозможно рекомендовать решение, не зная, какие зависимости в настоящее время принимает каждый слой.
Вы можете сделать это:
Service Layer
, а не на уровне контроллера (обычно должно быть на уровне контроллера, но в вашем сценарии это не применимо).Microsoft.Extensions.DependencyInjection
NuGet в свой Service Layer
DependencyInjection
в Service Layer
.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;
}
}
}
IPProductService
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. Вы можете использовать его для своих проектов, вы можете определить/добавить любой компонент, который вам нужен.
Спасибо, сэр. У вас есть правильный сценарий для моей проблемы. Вы предлагаете создать новый проект для управления зависимостями для всех слоев?
Не беспокойтесь :), Да, вы можете представить проекты как брандмауэр и определить зависимости только как то, что вы разрешаете. Следуйте шагам примера проекта.
Покажите некоторый код, чтобы предоставить лучший пример того, что вы имеете в виду.