Поддерживать корень композиции при создании компонентов в цикле Parallel.Foreach (многопоточность) - PullRequest
2 голосов
/ 15 апреля 2019

Я пытаюсь найти правильный путь в цикле Parallel ForEach, чтобы не ссылаться на корень композиции, но создать компонент потока на основе компонента, на который есть ссылка в корне композиции.

Это корневой код композиции:

var builder = new ContainerBuilder();
builder.RegisterType<OperationFiscalCalendarSql>().As<IOperationCloser>().InstancePerDependency();
builder.RegisterType<SQLMessagePoller>().As<IMessagePoller>().SingleInstance();
...
var container = builder.Build();
using (var scope = container.BeginLifetimeScope())
{
...
}

и это код, на который есть ссылка в объекте опроса, который имеет цикл foreach:

Parallel.ForEach(messageHeaders, new ParallelOptions { MaxDegreeOfParallelism = _maxDegreeOfParallelism }, messageHeader => {
    ...
    var sapCloser = new OperationFiscalCalendarSql(closeObj, repostiory);
    ...                        
}); 

Примечание. Мне нужен экземпляр IOperationCloser вместо жесткого кодирования «нового» объекта OperationFiscalCalendarSql.

Я понимаю внедрение в конструктор. Я просто не знаю, как внедрить IOperationCloser, когда он находится в каком-либо цикле.

1 Ответ

1 голос
/ 17 апреля 2019

Вы можете добавить фабрику в свой Poller объект с помощью Func<IOperationCloser>, а затем получить новый экземпляр в цикле ForEach.

В вашем случае может быть даже лучше создать свой собственный ILifetimeScope.Вы можете сделать это, введя ILieetimeScope в Poller и затем вызвать BeginLifetimeScope и Resolve в цикле.

Parallel.ForEach(messageHeaders, ..., m => {
    using(ILifetimeScope childScope = scope.BeginLifetimeScope()){
        var param1 = new TypedParameter(m);
        var closer = childScope.Resolve<IOperationCloser>(param1);
    });
});
...