7

У меня есть решение ASP.NET 5 dnxcore с некоторыми проектами, чтобы отделить свою логику:asp.net в нескольких проектах

  • API
  • ядра (с услугами для бизнеса-логики)
  • DAL (хранилище интерфейсов)
  • Entity Framework (Реализации хранилища)

Теперь я использую DI называть свои услуги в сопзЬ ructors моих контроллеров API:

private readonly IMyService _myService; 
public Controller(IMyService myservice){ _myService = myService; } 

услуга в моем ядре получить репозиторий через инъекцию конструкторы тоже:

private readonly IMyRepository _myRepo; 
public MyService(IMyRepository myRepo){ _myRepo = myRepo; } 

В настоящее время мне нужно определить мой DI контейнер в классе запуска моего API, чтобы сделать он работает.

Мой вопрос: как я могу поместить «здание» контейнера DI в хранилищах в своих сервисах в моем Core-проекте. Таким образом, мой API слабо связан с тем, что мои службы используют Entity Framework, поэтому я могу изменить, например, mongodb, не меняя проект API.

ответ

6

Вопрос в том, как я могу поместить «здание» контейнера DI в своих сервисах в моем Core-проекте. Таким образом, мой API слабо связан с тем, что мои службы используют Entity Framework, поэтому я могу изменить, например, mongodb, не меняя проект API.

Вы могли бы, но вы не должны сделать это.

Зависимость Инъекция - это практика создания свободно связанных классов во всех библиотеках, которые могут быть подключены (часто разными способами).

Однако каждая заявка должна иметь composition root, которая является одним местом в приложении, где мы помещаем код . Наш первый инстинкт как разработчики - попытаться скомпилировать код связи в свою собственную библиотеку, но это желание, с которым вам следует сопротивляться. См. composition root reuse.

При этом многие контейнеры DI имеют возможность организовать конфигурацию определенных частей приложения с помощью модулей. В Autofac - документация для modules is here.

+0

У вас есть примеры для новой инъекции зависимости aspnet 5? Благодарю. –

7

Вы можете легко добавить метод расширения IServiceCollection в свой уровень сервиса и использовать его для регистрации своих зависимостей. Затем в процессе запуска вы вызываете метод на уровне сервиса без ссылки на EntityFramework в своем веб-приложении.

using Microsoft.Extensions.DependencyInjection; 
using Microsoft.Extensions.DependencyInjection.Extensions; 

namespace your.service.layer 
{ 
    public static class MyServiceCollectionExtensions 
    { 
     public static IServiceCollection AddMyServiceDependencies(this IServiceCollection services) 
     { 
      services.AddScoped<My.Data.Tier.DbContext, My.Data.Tier.DbContext>(); 
     } 
    } 

} 

запуска:

using your.service.layer; 

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddMyServiceDependencies(); 
} 

Теперь ваше веб-приложение нуждается только ссылку на ваш сервисный уровень и не напрямую зависит от EntityFramework.

+0

Это лучшая практика? –

+0

Пожалуйста, обратитесь к [вопросу, который я недавно спросил] (http://stackoverflow.com/questions/42428571/transitive-references-in-net-core-1-1). При таком подходе вы столкнулись бы с той же проблемой, что и раньше: ваш веб-проект будет иметь ссылку на ваш.service.layer, а поскольку ваш .service.layer будет ссылаться на конкретные реализации, _transitivity_, ваш веб-проект будет ссылку your.service.layer. – Franco

+0

Да будет транзитивная зависимость. Я сам поместил большую часть своего кода в проекты библиотеки классов, поэтому для меня основное приложение для веб-приложений и консолей - это просто корень композиции для подключения зависимостей и конфигурации. Я не вижу в этом проблемы. –

0

See this question, У меня такая же проблема, потому что мое приложение не зависит от базы данных, а базе по запросу нужно будет переключаться между документами, ориентированными на базу данных (noSQL) и трансакциональной базой данных (SQL).

0

Как заявили NightOwl888, у вас должна быть CompositionRoot в вашем приложении, где установлены все ваши зависимости. Что я сделал: 1. Создайте библиотеку базового класса с именем CompositionRoot. 2. Добавьте класс для обработки ваших зависимостей:

public class DependencyMapper 
{ 
    public static void SetDependencies(IServiceCollection serviceCollection, IConfigurationRoot configuration) 
    { 
     serviceCollection.AddEntityFramework() 
         .AddDbContext<SonoPeopleContext>(options => 
                 options.UseSqlServer(configuration["Data:DefaultConnection:ConnectionString"]) 
                 );    

     MapperConfiguration mapperConfiguration = new MapperConfiguration(cfg => 
     { 
      cfg.AddProfile(new AutoMapperProfileConfiguration()); 
     }); 
     serviceCollection.AddSingleton<IMapper>(sp => mapperConfiguration.CreateMapper()); 

     serviceCollection.AddScoped<IUserService, UserService>(); 

    } 
} 

Тогда вы ссылаетесь ваш CompositionRoot в проекте MVC и в вашем Startup.cs вы просто делаете

DependencyMapper.SetDependencies(services, Configuration); 

Вот и все.