ПростойИнжектор. Как разрешить экземпляры с параметрами, которые можно оценить только во время выполненияC#

Место общения программистов C#
Ответить
Anonymous
 ПростойИнжектор. Как разрешить экземпляры с параметрами, которые можно оценить только во время выполнения

Сообщение Anonymous »

В моей программе много объектов, которые создаются во время выполнения и имеют как минимум один параметр. Существует множество вложенных классов, в которых оцениваются новые данные, необходимые для следующих внутренних экземпляров.
Сначала позвольте мне кратко описать структуру, а затем я предоставлю вам упрощенный пример.
Описание структуры.
  • Пользователь отправляет строковый запрос ->
  • Программа определяет IRequestContext и ICommand ->
  • Код: Выделить всё

    ICommand.Execute(IRequestContext)
    вызывается ->
  • При выполнении создаются IStep[] и IPlan(IStep[]) через фабрику и отправляются в планировщик ->< /li>
    В определенное время планировщик запускает IPlan с IRequestContext.
  • выполняется шаг за шагом путем вызова IObservable IStep.Make(IRequestContext) ->
  • Реализации IStep содержат экземпляры буфера для совместного использования результат их выполнения в рамках текущего плана. Он не возвращается, но необходимо сформировать итоговый отчет, но не только для этого. У буфера не может быть интерфейса, потому что это все-таки хранилище данных.
  • содержит перечисление Result и IMessageBuilder. В IMesageBuilder есть только 1 метод Build().
Подробнее
Каждый класс имеет множество зависимостей, таких как интерфейсы для работы с базой данных, локализация, API связи. Эти зависимости регистрируются в корне композиции. В данном случае это не проблема.
Экземпляр IRequestContext создается во время выполнения для каждого запроса пользователя. От него зависят IStep, IMessageBuilder и всевозможные буферы. Поэтому я не могу просто зарегистрировать SomeMessageBuilder, потому что необходимые данные для построителя создаются во время выполнения шага. И разные запросы не могут использовать один и тот же экземпляр построителя сообщений или буфера.
Для каждой реализации IMessageBuilder будет разное количество и типы параметров. Вот почему я не могу изменить интерфейс, чтобы принимать такие объекты, как IMessageBuilder.Build(Entity1, Entity2, ...). Поэтому мне приходится создавать и регистрировать фабрики для каждой реализации IMessageBuilder. В результате каждая реализация IStep зависит от IFactory.
Каждая реализация IPlan имеет это собственная фабрика, которая создает уникальную комбинацию шагов. Кроме того, я использую реализацию составного шаблона для таких шагов, как CompositeStep(IStep[] шаг) : IStep. Поэтому мне необходимо зарегистрировать фабрику для каждой реализации IStep, и мне нужно зарегистрировать фабрику для каждого CompositeStep, который состоит из разных шагов.
Упрощенный пример
Упрощенный пример
Упрощенный пример h3>
Имейте в виду, что у меня есть дюжина различных реализаций IPlan, которые могут использовать одни и те же шаги.
Некоторые интерфейсы и классы для пояснения.< /p>

Код: Выделить всё

public interface IPlan{
IObservable Execute(TContext context);
bool IsReadyToGoNext(TReport report);
}
public interface IStep{
IObservable Make(TContext context);
}
public interface IFactory
{
TObject Create(T1 param);
}

public interface IMessageBuilder{
SendMessage Build();
}
public class CreateMessageBuilder : LocalizedMessageBuilder, IMessageBuilder
{
public CreateMessageBuilder(long chatId, CultureInfo info
, ILocalizationProvider localizationProvider, int minSymbols, int maxSymbols)
{...}
public  void SetUser(UserRepresentation representation){...};
public void SetSirena(SirenRepresentation sirena){...};
public void IsUserAllowedToCreateSirena(bool isAllowed){...};
public void IsTitleValid(bool isValid){...};
public override SendMessage Build(){...};
}
Пример фабрики планов:

Код: Выделить всё

public class CreateSirenaPlanFactory : IFactory
{
private readonly Container container;
private readonly IFactory messageBuilderFactory;
private readonly IFactory bufferFactory;

public CreateSirenaPlanFactory(Container container
, IFactory messageBuilderFactory
, IFactory  bufferFactory)

{
this.container = container;
this.messageBuilderFactory = messageBuilderFactory;
this.bufferFactory = bufferFactory;
}

public IPlan Create(IRequestContext context)
{
CreateMessageBuilder messageBuilder = messageBuilderFactory.Create(context);
CreateSirenaStep.Buffer buffer = bufferFactory.Create(messageBuilder);

//Same buffer instance has to be shared between group of steps below
//But for each new request a new instance of plan and of buffer has to be created
var validation = new CompositeCommandStep([
container.GetInstance(),
container.GetInstance()
]);

IStep[] steps = [
container.GetInstance(),
validation,
container.GetInstance(),
];
return new CommandPlan(CreateSirenaCommand.NAME,steps);
}
}
Вопрос
Как это привязать? Я не хочу создавать фабрику для каждой реализации IStep, которая зависит от одного и более параметров, создаваемых во время выполнения. И я вообще не знаю, как привязать буфер в этой ситуации, поскольку у SimpleInjector нет контекста.
P.S.
Когда я работал с движком Unity и с Zenject/ В Extenject было гораздо больше возможностей разделить контексты привязок и создать условные привязки для экземпляров из определенной фабрики. Жаль, что в SimpleInjector нет таких инструментов.
Потому что для каждого экземпляра плана я мог создать контекст. И для каждого контекста будет создан 1 экземпляр буфера. Более того, мне не нужно создавать фабрику для каждого экземпляра, которому нужны параметры, потому что я могу просто связать собственную фабрику с параметрами. Для меня было огромным удивлением, когда я узнал, что документация не предоставляет информацию о контексте, а только об областях видимости. Но я не могу создать экземпляр буфера в области, потому что область будет закрыта, когда метод Create завершит свою работу, и экземпляр будет удален, как я понял из документации. Возможно, я могу использовать область Flowing, однако я до сих пор не понимаю, как разрешить экземпляр с параметрами.

Подробнее здесь: https://stackoverflow.com/questions/787 ... ld-be-eval
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»