ASP.NET Ядро DI с простым инжектором, совместно использующим DbContext

#c# #asp.net-core #dependency-injection #entity-framework-core #simple-injector

#c# #asp.net-ядро #внедрение зависимостей #сущность-фреймворк-ядро #простой инжектор

Вопрос:

Я настраиваю ASP.NET Основной проект и следование шаблону CQRS, основанному на моей работе над проектом Tripod. Я следовал руководству по интеграции простого инжектора, но немного озадачен одним моментом… Я хочу продолжать использовать UseInMemoryDatabase опцию для тестирования и могу найти примеры этого только с использованием метода Core DI AddDbContext .

Мой DbContext реализует несколько интерфейсов:

 public class EntityDbContext : DbContext,
    IUnitOfWork,
    IReadEntities,
    IWriteEntities
{
    // code here
}
  

Я делаю это в Startup.ConfigureServices методе:

 services.AddDbContext<EntityDbContext>(options => options.UseInMemoryDatabase("Snoogans"));
  

и следуя руководству по интеграции SI, это при запуске.Метод настройки:

 container.Register<IUnitOfWork, xxxx>();
container.Register<IReadEntities, xxxx>();
container.Register<IWriteEntities, xxxx>();
  

Могу ли я получить регистрацию ядра через crosswire для подключения к цели для каждого из них или я должен просто регистрировать контекст непосредственно в SI?

== Я играю с оригинальной концепцией от Tripod:

 var contextRegistration =
    lifestyle.CreateRegistration<EntityDbContext, EntityDbContext>(container);
container.AddRegistration(typeof(EntityDbContext), contextRegistration);
container.AddRegistration(typeof(IUnitOfWork), contextRegistration);
container.AddRegistration(typeof(IWriteEntities), contextRegistration);
container.AddRegistration(typeof(IReadEntities), contextRegistration);
  

пытаюсь сделать все с помощью SI, но не уверен, как я доберусь до регистрации для 3 интерфейсов:

 container.Register<EntityDbContext>(() =>
{
    var optionsBuilder =
        new DbContextOptionsBuilder<EntityDbContext>().UseInMemoryDatabase("Snoogans");
    return new EntityDbContext(optionsBuilder.Options);
});
container.AddRegistration<IUnitOfWork>(xxxx);
container.AddRegistration<IReadEntities>(xxxx);
container.AddRegistration<IWriteEntities>(xxxx);
  

Ответ №1:

Могу ли я получить регистрацию ядра через crosswire для подключения к цели для каждого из них или я должен просто регистрировать контекст непосредственно в SI?

Возможны оба варианта. Вы можете зарегистрировать DbContext непосредственно в Simple Injector. Обычно это наиболее очевидный выбор, поскольку ваш DbContext является компонентом приложения. Компоненты приложения обычно должны регистрироваться в вашем контейнере приложения (т.Е. Simple Injector), а не в системе регистрации фреймворка (т.Е. ServiceCollection ).

Однако, когда дело доходит до регистрации DbContext , существует некоторая тесная интеграция с ASP.NET Система конфигурации ядра. Это может упростить регистрацию там и просто выполнить перекрестное подключение из простого инжектора. Это позволяет системе конфигурации сохранять контроль над созданием и уничтожением DbContext. Это становится особенно ценным при выполнении таких действий, как объединение DbContext, поскольку эта функциональность объединения тесно связана с этим конфигурационным и регистрационным API.

Обычно оба варианта довольно просты, но поскольку ваш DbContext реализует несколько интерфейсов, которые вы хотите зарегистрировать отдельно, это усложняет вашу регистрацию. Это также имело бы место в случае, если вы также используете встроенный контейнер DI, так что это не относится конкретно к Simple Injector.

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

 var reg = Lifestyle.Scoped.CreateRegistration(() =>
    {
        var optionsBuilder =
            new DbContextOptionsBuilder<EntityDbContext>().UseInMemoryDatabase("Snoogans");
        return new EntityDbContext(optionsBuilder.Options);
    },
    container);

container.AddRegistration<IUnitOfWork>(reg);
container.AddRegistration<IReadEntities>(reg);
container.AddRegistration<IWriteEntities>(reg);
  

В случае, если вы решили подключить свой DbContext из системы конфигурации .NET Core, ваша конфигурация будет выглядеть следующим образом:

 // Add to the built-in ServiceCollection
services.AddDbContext<EntityDbContext>(options => options.UseInMemoryDatabase("Snoogans"));

// Cross-wire in Simple Injector
container.CrossWire<EntityDbContext>(app);

// Pull that registration out of Simple Injector and use it for the interface registrations
var reg = container.GetRegistration(typeof(EntityDbContext)).Registration;

// Same as before
container.AddRegistration<IUnitOfWork>(reg);
container.AddRegistration<IReadEntities>(reg);
container.AddRegistration<IWriteEntities>(reg);
  

Если бы вы использовали не простой инжектор, а исключительно встроенный DI-контейнер .NET Core, регистрация выглядела бы следующим образом:

 services.AddDbContext<EntityDbContext>(options => options.UseInMemoryDatabase("Snoogans"));

services.AddScoped<IUnitOfWork>(c => c.GetRequiredService<EntityDbContext>());
services.AddScoped<IReadEntities>(c => c.GetRequiredService<EntityDbContext>());
services.AddScoped<IWriteEntities>(c => c.GetRequiredService<EntityDbContext>());