Как передать параметр времени выполнения как часть разрешения зависимостей для универсального класса? - PullRequest
0 голосов
/ 11 апреля 2019

Здесь был дан ответ на похожий вопрос:

Как передать параметр времени выполнения как часть разрешения зависимости?

Однако мне было интересно, как этоможет быть сделано при регистрации универсального класса?

Обычно я регистрирую его следующим образом:

services.AddScoped(typeof(ITest<>), typeof(Test<>));

Но что, если я хочу передать параметр времени выполнения в конструктор?Без использования DI это было бы что-то вроде:

new Test<MyClass>(string mystring, int myInt)

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

Альтернативой может быть получение экземпляра без передачи параметра времени выполнения в конструкторе и вместо этого использования метода установщика после получения точного экземпляра.Однако я хотел бы избежать этого, потому что каждый раз после получения экземпляра вы должны не забывать вызывать метод setter.

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

РЕДАКТИРОВАТЬ: После прочтения очень полезного ответа Стивена я обновил вопрос более конкретным примером: Следующий пример находится внутри некоторого метода:

//instance of repository are passed inside constructor of class
//calling some to update/insert
//IMPORTANT - calling external service I want save parameters to db no matter what
using(var ctx=new DbContext())
{
//create log object
ctx.logs.add(Obj)
ctx.save()
}
//some code after

Допустим, я хочу быть непротиворечивым и вызвать метод моего репозитория logging, добавить туда объект logging и сохранить все в базе данных. Однако каждый репозиторий в конструкторе принимает DbContext, который зарегистрирован как scoped (за один запрос)).Если это внутри транзакции, сохранение зависит от кода после вызова внешней службы, и он может генерировать исключение и ничего не сохранять.

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

Моя ситуация в чем-то похожа, но она собирается для некоторых данных в БД на основе текущего пользователя, и я не хочу передавать один и тот же параметр многочисленным методам, но только внутри конструктора класса.

1 Ответ

2 голосов
/ 11 апреля 2019

Общее решение для внедрения примитива значений конфигурации в компоненты вашего приложения состоит в том, чтобы извлечь их в Параметр Object . Это дает этим значениям новый, однозначный тип, который можно зарегистрировать в вашем контейнере:

// Parameter Object
public TestConfiguration
{
    public string Mystring;
    public int MyInt;
}

// (Generic) class using the Parameter Object
public class Test<T>
{
    public Test(TestConfiguration config) { ... }
}

// Registering both
services.AddScoped(typeof(ITest<>), typeof(Test<>));
services.AddSingleton(new TestConfiguration { Mystring = ..., Myint = ... });

Значения конфигурации не считаются данными времени выполнения , так как их значения известны при запуске и постоянны в течение всего времени приложения. Вот почему вы можете предоставить их конструкторам компонентов вашего приложения.

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

Вместо передачи данных времени выполнения через конструктор, вы должны либо:

  1. Передача данных времени выполнения через вызовы методов API или

  2. Извлечение данных времени выполнения из определенных абстракций, которые позволяют разрешать данные времени выполнения.

Более подробную информацию о передаче данных времени выполнения можно найти здесь .

...