Po zapytaniu moich own question o tym, jak obsługiwać scopingu ...Właśnie doszedłem do tego rozwiązania: nie sądzę, że jest to idealne rozwiązanie, ale na razie nie mogłem znaleźć żadnego innego rozwiązania.
W moim przykładzie mam do czynienia z ServiceBusTrigger.
Ponieważ używam SimpleInjector, implementacja interfejsu IJobActivator wygląda tak:
public class SimpleInjectorJobActivator : IJobActivator
{
private readonly Container _container;
public SimpleInjectorJobActivator(Container container)
{
_container = container;
}
public T CreateInstance<T>()
{
return (T)_container.GetInstance(typeof(T));
}
}
Tutaj mam do czynienia z wyzwalane webjobs.
Więc mam dwie zależności:
pojedyncza:
public interface ISingletonDependency { }
public class SingletonDependency : ISingletonDependency { }
I jeszcze, że muszą żyć tylko czas moja funkcja jest wyzwalany:
public class ScopedDependency : IScopedDependency, IDisposable
{
public void Dispose()
{
//Dispose what need to be disposed...
}
}
Tak więc, aby hav e proces, który działa niezależnie od webjob. Mam obudowane mój proces w klasie:
public interface IBrokeredMessageProcessor
{
Task ProcessAsync(BrokeredMessage incommingMessage, CancellationToken token);
}
public class BrokeredMessageProcessor : IBrokeredMessageProcessor
{
private readonly ISingletonDependency _singletonDependency;
private readonly IScopedDependency _scopedDependency;
public BrokeredMessageProcessor(ISingletonDependency singletonDependency, IScopedDependency scopedDependency)
{
_singletonDependency = singletonDependency;
_scopedDependency = scopedDependency;
}
public async Task ProcessAsync(BrokeredMessage incommingMessage, CancellationToken token)
{
...
}
}
Więc teraz, gdy zaczyna webjob, muszę się zarejestrować moje zależności zależności ich zakresy:
class Program
{
private static void Main()
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new ExecutionContextScopeLifestyle();
container.RegisterSingleton<ISingletonDependency, SingletonDependency>();
container.Register<IScopedDependency, ScopedDependency>(Lifestyle.Scoped);
container.Register<IBrokeredMessageProcessor, BrokeredMessageProcessor>(Lifestyle.Scoped);
container.Verify();
var config = new JobHostConfiguration
{
JobActivator = new SimpleInjectorJobActivator(container)
};
var servicebusConfig = new ServiceBusConfiguration
{
ConnectionString = CloudConfigurationManager.GetSetting("MyServiceBusConnectionString")
};
config.UseServiceBus(servicebusConfig);
var host = new JobHost(config);
host.RunAndBlock();
}
}
i to jest wyzwalane zadanie:
- Ma tylko jedną zależność: kontener IoC. Ponieważ ta klasa jest częścią mojego katalogu głównego kompozycji, powinno być w porządku.
Obsługuje zakres do wyzwalanej funkcji.
public class TriggeredJob
{
private readonly Container _container;
public TriggeredJob(Container container)
{
_container = container;
}
public async Task TriggeredFunction([ServiceBusTrigger("queueName")] BrokeredMessage message, CancellationToken token)
{
using (var scope = _container.BeginExecutionContextScope())
{
var processor = _container.GetInstance<IBrokeredMessageProcessor>();
await processor.ProcessAsync(message, token);
}
}
}
można opracować trochę? Czy próbujesz uzyskać zakres "zadania" dla obiektów wychodzących z kontenera, podobnie jak w przypadku pojedynczego żądania w standardowej aplikacji internetowej? – Veatch
Tak. Zmieniłem to pytanie. Więcej informacji można znaleźć w poście na blogu, który łączyłem. –
Zakładając, że korzystasz z aplikacji konsolowej, powinieneś używać DI tak jak w dowolnej aplikacji konsolowej. Biorąc to pod uwagę, jedyną metodą, którą znalazłem, jest użycie czegoś podobnego niż anty-wzór w poście na blogu. Mogę podać przykład używając Ninject na życzenie. – lopezbertoni