Как зарегистрировать зависимости на основе класса, от которого они требуются (используя встроенный IOC-контейнер в ASP CORE) - PullRequest
1 голос
/ 03 октября 2019

Я пытаюсь зарегистрировать разные реализации одного интерфейса и в зависимости от классов, использующих эти реализации, определенную для передачи.

public interface ITest { }
public class Test1 : ITest { } 
public class Test2 : ITest { }

public class DoSmthWhichCurrentlyNeedsTest1
{
    private ITest test;

    public DoSmthWhichCurrentlyNeedsTest1(ITest test)
    {
        this.test = test;
    }
}

public class DoSmthWhichCurrentlyNeedsTest2
{
    private ITest test;

    public DoSmthWhichCurrentlyNeedsTest2(ITest test)
    {
        this.test = test;
    }
}

Текущее решение:

services.AddTransient(x=>new DoSmthWhichCurrentlyNeedsTest1(new Test1()));
services.AddTransient(x=>new DoSmthWhichCurrentlyNeedsTest2(new Test2()));

Это работает хорошо, если у вас нет классов с большим количеством зависимостей, где "x.GetRequiredService" должен вызываться для каждой зависимости в конструкторе.

То, что я ищу, выглядит примерно так:

services.AddTransient<ITest, Test1>
    (/*If ITest is required by DoSmthWhichCurrentlyNeedsTest1*/);
services.AddTransient<ITest, Test2>
    (/*If ITest is required by DoSmthWhichCurrentlyNeedsTest2*/);

Есть ли другой способ, который я пропустил для этой цели?

Ответы [ 2 ]

1 голос
/ 05 октября 2019

Это работает хорошо, если у вас нет классов с большим количеством зависимостей, где "x.GetRequiredService" должен вызываться для каждой зависимости в конструкторе.

Это хорошее применение. чехол для ActivatorUtilities.CreateInstance. Вот пример:

services.AddTransient(sp =>
    ActivatorUtilities.CreateInstance<DoSmthWhichCurrentlyNeedsTest1>(sp, new Test1()));

ActivatorUtilities.CreateInstance<T> создает экземпляр указанного типа (в данном примере DoSmthWhichCurrentlyNeedsTest1), используя комбинацию контейнера DI и любых передаваемых вами дополнительных параметров. Первый передаваемый аргумент - это IServiceProvider, и любые дополнительные параметры используются для предоставления явных значений по типу.

В показанном примере ActivatorUtilities.CreateInstance будет:

  • Искатьподходящий конструктор для DoSmthWhichCurrentlyNeedsTest1 и анализ его параметров.
  • Сопоставьте все, что вы предоставляете в качестве дополнительных параметров, с присваиваемым типом по отношению к параметрам конструктора. Мы предоставляем экземпляр Test1, который можно назначить на ITest, чтобы он использовался на следующем шаге.
  • Создайте экземпляр DoSmthWhichCurrentlyNeedsTest1, сопоставив параметры с указанными вами значениями. Для всего, что вы не предоставили, он пытается разрешить значения из контейнера DI, используя GetService.

Это позволяет вам не беспокоиться о подключении всех предоставленных DIзависимости для DoSmthWhichCurrentlyNeedsTest1, в то же время позволяя вам указать те, которые делают , о которых вы заботитесь.

0 голосов
/ 04 октября 2019

Вот рабочая демонстрация, как показано ниже:

1.Интерфейс:

public interface ITest {
    string play();
}

2. класс реализации:

public class Test1 : ITest
{
    public string play()
    {
        return "111";
    }
}
public class Test2 : ITest
{
    public string play()
    {
        return "222";
    }
}

3. тестовый класс:

public class DoSmthWhichCurrentlyNeedsTest1
{
    private IEnumerable<ITest> test;

    public DoSmthWhichCurrentlyNeedsTest1(IEnumerable<ITest> test)
    {
        this.test = test;
    }  
    public string Get()
    {
        var flag = test.FirstOrDefault(h => h.GetType().Name == "Test1");
        var value = flag?.play();
        return value;
    }
}
public class DoSmthWhichCurrentlyNeedsTest2
{
    private IEnumerable<ITest> test;

    public DoSmthWhichCurrentlyNeedsTest2(IEnumerable<ITest> test)
    {
        this.test = test;
    }
    public string Get() 
    {
        var flag = test.FirstOrDefault(h => h.GetType().Name == "Test2");
        var value = flag?.play();
        return value;
    }
}

4.Startup.cs:

services.AddTransient<ITest, Test1>();
services.AddTransient<ITest, Test2>();

5.Результат: enter image description here

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