Сохранение корня композиции при параллельном создании компонентов.Цикл Foreach (многопоточность)

#multithreading #autofac

#многопоточность #autofac

Вопрос:

Я пытаюсь изучить правильный путь внутри параллельного цикла 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:

Вы можете внедрить фабрику в свой 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);
    });
});