好吧,我正在使用 Autofact 来制作我的 (IoC)。我在我的第一个 Builder
for each
上有一个 IServiceProvider 的注册列表
我正在使用“使用范围...”来初始化服务。 IServiceProvider 是一个接口,有两个方法“StartService”和“StopService”,我目前需要通过执行“StartService”来初始化服务。
问题实际上是我注册了 9 个服务,我尝试执行 foreach 来初始化 9 个服务但它不起作用,初始化其他服务的正确方法是什么?目前我只是用 using scope ...
初始化一项服务,我想初始化所有服务,我在 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
答案 0 :(得分:0)
您的代码存在三个问题:
(注意:我只在 c# 中使用 Autofac,所以答案将使用该语言,但应该很容易翻译成 VB :)
对于第一个问题,为了访问你所有实现 IServiceProvider 的服务,你需要解析为:
IEnumerable<IServiceProvider> services;
然后您可以为每个循环创建一个并为每个循环调用 StartService。
另一种选择是在注册期间使用激活的事件:
builder.RegisterType<MyService>().As<IServiceProvider>()
.OnActivated(ctx => ctx.Instance.StartService());
这样的话它只会在第一次 IServiceProvider 得到解析时启动服务,如果你希望它们在容器构建时立即启动,你可以使用自动激活,你的注册变成:
builder.RegisterType<MyService>().As<IServiceProvider>()
.OnActivated(ctx => ctx.Instance.StartService())
.AutoActivate();
现在为了正确调用StopService,你还有两个选择:
首先,更简单但更具侵入性的是,您的 IServiceProvider 接口可以实现 IDisposable 而不是使用 StopService。
所以当容器被释放时,Dispose 会被自动调用。
当然这是一个突破性的变化,所以另一个选择是在注册期间添加另一个生命周期事件:
builder.RegisterType<MyService>().As<IServiceProvider>()
.OnActivated(ctx => ctx.Instance.StartService())
.AutoActivate()
.OnRelease(instance => instance.StopService());
当您的容器被释放时,将调用 release 事件,并停止服务。
对于最后一个问题,您正在创建范围、解析服务然后释放范围,因此如果您尝试在容器级别再次解析您的服务,它们将不可见。
对于这种情况,您应该简单地调用:
container.Resolve<IEnumerable<IServiceProvider>>();
如果您使用了 autoactivate 事件,这当然不再需要了,Autofac 将为您完成。