Well I am using Autofact to make my (IoC). I have a list of registration of IServiceProvider on my variable Builder
in my firt for each
I am using a "using scope ..." to initialize the service. IServiceProvider is an interface that has two methods "StartService" and "StopService" I currently need to initialize the services by executing "StartService".
The problem actually is that I have like 9 services registered, I tried to do a foreach to inizialize the 9 services but it doesn't work, what is the correct way to inizialize the other services? currently just I'm initalize one service with the using scope ...
, I want initialice all services, I have these services store in the Builder.
Protected Property Services As List(Of IServiceProvider)
Public Sub StartServices(applicationDirectory As String) 'As List(Of IServiceProvider).
Dim Builder = New ContainerBuilder
Me.applicationDirectory = applicationDirectory
Try
Dim serviceProviderTypes = Directory.EnumerateFiles(applicationDirectory).Where(Function(filename) filename.EndsWith(".dll")).[Select](Function(filepath) Assembly.LoadFrom(filepath)).SelectMany(Function(assembly) assembly.GetTypes().Where(Function(type) GetType(IServiceProvider).IsAssignableFrom(type) AndAlso type.IsClass))
For Each serviceProviderType In serviceProviderTypes
Builder.RegisterType(serviceProviderType).[As](Of IServiceProvider)()
Next
Dim container = Builder.Build()
Using scope = container.BeginLifetimeScope()
Dim app = scope.Resolve(Of IServiceProvider)()
app.StartService()
End Using
Catch ex As Reflection.ReflectionTypeLoadException
Throw ex
End Try
There are three problems with your code :
(NOTE: I only use Autofac in c# so answer will be in that language, but it should be easy to translate to VB :)
For the first Issue, in order to access all your services that implement IServiceProvider, you need to resolve as :
IEnumerable<IServiceProvider> services;
Then you can make a for each loop and call StartService for each of them.
Another option is to use an activated event during registration :
builder.RegisterType<MyService>().As<IServiceProvider>()
.OnActivated(ctx => ctx.Instance.StartService());
In that case it will only Start Service the first time IServiceProvider gets resolved, if you want them to be started immediately when container is built, you can use Auto activate, your registration becomes :
builder.RegisterType<MyService>().As<IServiceProvider>()
.OnActivated(ctx => ctx.Instance.StartService())
.AutoActivate();
Now in order to properly call StopService, you also have two options:
First, simpler but more intrusive, your IServiceProvider interface can implement IDisposable instead of using StopService.
So when container is released Dispose will be called automatically.
Of course this is a breaking change, so the other option is to add another lifetime event during registration :
builder.RegisterType<MyService>().As<IServiceProvider>()
.OnActivated(ctx => ctx.Instance.StartService())
.AutoActivate()
.OnRelease(instance => instance.StopService());
When your container will be disposed, the release event will be called, as well as stop service.
For the last issue, you are creating a scope, resolve a service then release the scope, so if you try to resolve your services again at container level, they will not be visible.
For that case, you should simply call :
container.Resolve<IEnumerable<IServiceProvider>>();
If you used the autoactivate event this is of course not needed anymore, Autofac wil have done it for you.