Добавить сервис с областью при создании новой области - PullRequest
0 голосов
/ 11 апреля 2020

Можно ли добавить службу к IServiceProvider при создании новой области?

Например, область создается следующим образом:

using (var scope = Services.CreateScope())
{
    // Register some service using "AddScoped"
    scope.??.AddScoped<IOrganizationIdProvider, OrganizationIdProvider>((x) => { return new OrganizationIdProvider("dynamic-parameter")});

    // Resolve service
    scope.ServiceProvider.GetService<IOrganizationIdProvider>();

}

Служба должна быть разрешена, когда создание новых экземпляров в области.

Ответы [ 2 ]

2 голосов
/ 13 апреля 2020

@ Nkosi уже упоминал, что вы не можете делать новые регистрации в MS.DI после создания контейнера. Но даже если бы вы могли изменить контейнер во время полета, это плохая идея, поэтому большинство DI-контейнеров не поддерживают такую ​​функцию. Например, новейшие версии Autofa c и Ninject недавно удалили такую ​​функцию, а документация Simple Injector объясняет , почему у нее никогда не было этой функции.

Но вы можете достичь того, что вы хотите внести небольшие изменения в ваш код. Вероятно, самый простой способ реализовать это - сделать изменение, вводя параметр dynamici c через внедрение свойства вместо внедрения конструктора. Например:

Изменения в коде приложения:

public class OrganizationIdProvider : IOrganizationIdProvider
{
    // Only required code change (notice that the interface doesn't change, this
    // property is an implementation detail)
    public string DynamicParameter { get; set; }
}

Конфигурация контейнера:

// Register the implementation by itself to allow it to be requested by your infrastructure
services.AddScoped<OrganizationIdProvider>();

// Register the provider by its interface so it can be injected into application components
services.AddScoped<IOrganizationIdProvider>(c => c.GetService<OrganizationIdProvider>());

Использование:

using (var scope = Services.CreateScope())
{
    // Here we resolve the OrganizationIdProvider *implementation*
    var provider = scope.ServiceProvider.GetRequiredService<OrganizationIdProvider>();

    // Set the runtime parameter
    provider.DynamicParameter = "dynamic-parameter";

    // Resolve service that might have a dependency on IOrganizationIdProvider.
    var handler =
        scope.ServiceProvider.GetRequiredService(typeof(IMessageHandler<DoSomething>));

    // Use the service
    handler.Handle(new DoSomething());
}

Конечно, есть и другие варианты работы с данными времени выполнения, но для этого я бы рекомендовал вам прочитать эту серию на DI Composition Models .

0 голосов
/ 11 апреля 2020

То, чего вы хотите достичь, невозможно.

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

public class IdClass1 : ParentClassWithId
{}

public class IdClass2 : ParentClassWithId
{}
public class ParentClassWithId
{
    public string Id { get; set; }
}

тогда ваш IOrganizationIdProvider станет IOrganizationIdProvider<T>, где T - это класс.

public interface IOrganizationIdProvider<T>
{
    //code   
}

Для кода многократного использования преобразуйте ваш основной OrganizationProvider класс в абстрактный

public abstract class OrganizationProvider<T>
{

}

, а затем для каждого из «Dynami c» вам нужен класс, чтобы использовать его:

public class OrganizationIdProvider1<T> : OrganizationProvider<T>, IOrganizationIdProvider<T>
{
    //Code
}

public class OrganizationIdProvider2<T> : OrganizationProvider<T>, IOrganizationIdProvider<T>
{
    //Code
}

при первоначальном внедрении зависимости вам нужно будет объявить все из возможных вариантов в этом примере:

scope.AddScoped<IOrganizationIdProvider<IdClass2>, OrganizationIdProvider2<IdClass2>>()
.AddScoped<IOrganizationIdProvider<IdClass1>, OrganizationIdProvider1<IdClass1>>();

, и вам понадобится немного логики c, чтобы получить правильный интерфейс, но это может решить вашу проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...