Контекст выполнения операции

222
15 сентября 2018, 16:10

Есть класс Dispatcher с набором public методов, которые вызываются извне. Каждый из методов - задача(Func<Task>), запускаемая в очереди (в один момент выполняется одна задача). Каждый из методов имеет большую вложенность выполнения (вызывается множество сервисов и других компонентов в процессе исполнения). На этапе выполнения задачи на разных уровнях вложенности необходимо собирать возникающие ошибки. Появилась идея использовать "Контекст выполнения". То есть какой-то статический класс, доступный везде в процессе выполнения задачи в очереди, чтобы не было необходимости пробрасывать данные(возникающие ошибки) из слоя в слой. Проблема в том, что таких Dispatcher-ов может быть много(а static класс общий для всех). Как лучше реализовать такой контекст выполнения операции в разрезе множество диспетчеров?

Answer 1

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

Интерфейс контекста

public interface IExecutionContext
{
  string Name { get; }
}

Реализация

public class ExecutionContext : IExecutionContext
{
  public string Name { get; private set; }
  public ExecutionContext(string name)
  {
    Name = name;
  }
}

Класс, который хочет знать о конетексте

public class ContextConsumer
{
  IExecutionContext _context;
  public ContextConsumer(IExecutionContext context)
  {
    _context = context;
  }
  public void Action()
  {
    Console.WriteLine(_context.Name);
  }
}

Диспетчер, который запускает действие. Он же создает контекст и дочерний контейнер

public class Dispatcher
{
  IUnityContainer _rootContainer;
  public Dispatcher(IUnityContainer container)
  {
    _rootContainer = container;
  }
  public void ExecuteSomething(string contextName)
  {
    var childContainer = _rootContainer.CreateChildContainer();
    var context = childContainer
        .Resolve<ExecutionContext>(new ParameterOverride("name", contextName));
    childContainer.RegisterInstance<IExecutionContext>(context);
    var consumer = childContainer.Resolve<ContextConsumer>();
    consumer.Action();
  }
}

Как использовать:

var container = new UnityContainer();
var dispatcher = container.Resolve<Dispatcher>();
for (var i = 0; i < 10; i++)
{
  var context = "myAwesomeContext" + i;
  dispatcher.ExecuteSomething(context);
}

Вывод

myAwesomeContext0
myAwesomeContext1
myAwesomeContext2
myAwesomeContext3
myAwesomeContext4
myAwesomeContext5
myAwesomeContext6
myAwesomeContext7
myAwesomeContext8
myAwesomeContext9

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

Answer 2

Ты можешь воспользоваться фабричным паттерном. Создаёшь фабрику со статичным методом для создания твоего диспатчера и где нужно его делаешь ;)
Можно посмотреть в сторону выполнения всех задач через класс Tasks, потому что в нём уже встроена эта логика, он не выбрасывает исключения во время выполнения, а при вызове Wait и Result отдаёт коллекцию необработанных исключений (если они есть). Но если нужно как-то восстанавливаться при ошибках такой подход не подойдёт :С

READ ALSO
Изменить данные XML файла

Изменить данные XML файла

Нужно из xml файла получать данные, по нажатию кнопки менять значение на 2 (+2)А вот как изменять данные из файла найти не могу нормально

257
PHP цикл выводит неправильную сумму

PHP цикл выводит неправильную сумму

Я создаю цикл от 0-100 и создаю определенные условияНапример, если число делится на 3 без остатка вывести строку, но у меня также есть условие,...

246
Telegram PHP получить ответ от бота

Telegram PHP получить ответ от бота

Подскажите, как мне лучше на php примерно будет реализовать задачуВ telegram есть бот (не мой), при написании ему сообщения он выдаёт ссылку

287
Не отображается карта яндекса

Не отображается карта яндекса

Хочу сделать карту яндекса на сайтеЗакидываю код в отдельный файл, все работает

231