After asking my own question about how to handle the scope ... I just came up with this solution: I do not think this is perfect, but at the moment I cannot find another solution.
In my example, I am dealing with ServiceBusTrigger.
Since I use SimpleInjector , the implementation of the IJobActivator interface looks like this:
public class SimpleInjectorJobActivator : IJobActivator { private readonly Container _container; public SimpleInjectorJobActivator(Container container) { _container = container; } public T CreateInstance<T>() { return (T)_container.GetInstance(typeof(T)); } }
Here I am dealing with Triggered webjobs.
So, I have two dependencies:
Syntax:
public interface ISingletonDependency { } public class SingletonDependency : ISingletonDependency { }
And one more that should support only the response time of my function:
public class ScopedDependency : IScopedDependency, IDisposable { public void Dispose() {
So, to have a process that runs independently of the webjob. I encapsulated my process in a class:
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) { ... } }
So, now that the webjob starts, I need to register dependencies based on their areas:
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(); } }
And this is a running job:
- Only one dependency: IoC container. Since this class is part of my composition root, it should be fine.
It handles the scope in a running function.
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); } } }
Thomas Dec 08 '15 at 1:28 2015-12-08 01:28
source share