我现在有一个API的插件热更新,已经实现
但每个插件都是一个独立的项目,需要进行服务注册,有没有办法可以实现
将插件内的service在 运行时 添加到 host applicaiton已经生成好ServiceProvider 是不可能的.
从设计上来说, 你的主程序不需要也不应该 要知道任何插件的细节.
可以说一说你的需求, 然后找到一个解决办法.
因为我单个插件(项目)、需要对实现的接口方法进行注入,
以便控制器使用或插件之间通讯,我知道如果不注入也可以传统的方式实现,
但我觉得违背了DI IOC的原则了
我在项目启动时 反射解析DLL,注入相关接口实现,这没问题
但我需要在项目启动之后,我上传一个dll文件,解析反射注入,
上传成功后,我通过查询IServiceCollection的对象 _services.BuildServiceProvider()
是可以查询到我成功注入相关服务,但实际并不起作用
@阿杰_joly:
Microsoft.Extensions.DependencyInjection.ServiceProvider 是做不到这个事情的. 因为在Service Collection.BuildServiceProvider的时候注册的services就固定下来了.
方案一:
主程序不应该在DI系统中去获得由插件注册的服务. 应该用插件规约系统来获取支持.
一旦插件能更改主程序的任何资源, 这将是一个灾难. 插件系统的安全性和隔离性是必须要考虑的问题.
例如
//路由operation给插件系统.
主程序.ServiceProvider.GetService<IPluginProvider>().RouteEvent(....);
//循环注册的所有插件,并找到一个实现.
主程序.ServiceProvider.GetService<IPluginProvider>().FindResource<T>().DoSomething();
//获得主程序的资源, 可能是主程序提供, 也可以由插件提供支持.
插件.LoadedContext.FindResource<I>();
方案二:
代理实现自己的ServiceProvider. 有这个代理提供真正的ServiceProvider, 并感知插件的注册/卸载. 生成新的真正的ServiceProvider. <span style="color: red;">这将带来无数的问题和BUG!</span>
BuildServiceProvider_Proxy(this IServiceCollection services) => new MyServiceProvider(services)
PluginChangeCallback ==> MyServiceProvider.Refresh();
MyServiceProvider:IServiceProvider{
realServiceProvider;
Refresh() => realServiceProvider=services.BuildServiceProvider();
GetService(Type type)=> if(type is IServiceProvider) ? this : realServiceProvider.GetService(type);
}