首页 新闻 会员 周边 捐助

我有一个模块化系统,可以在运行时“安装”插件,这些插件具有需要添加到 ServiceCollection 的服务。

0
悬赏园豆:100 [已解决问题] 解决于 2023-05-23 14:29

我现在有一个API的插件热更新,已经实现
但每个插件都是一个独立的项目,需要进行服务注册,有没有办法可以实现

阿杰_joly的主页 阿杰_joly | 初学一级 | 园豆:112
提问于:2023-05-09 20:12
< >
分享
最佳答案
0

将插件内的service在 运行时 添加到 host applicaiton已经生成好ServiceProvider 是不可能的.

从设计上来说, 你的主程序不需要也不应该 要知道任何插件的细节.

可以说一说你的需求, 然后找到一个解决办法.

收获园豆:100
czd890 | 专家六级 |园豆:14488 | 2023-05-10 12:08

因为我单个插件(项目)、需要对实现的接口方法进行注入,
以便控制器使用或插件之间通讯,我知道如果不注入也可以传统的方式实现,
但我觉得违背了DI IOC的原则了

阿杰_joly | 园豆:112 (初学一级) | 2023-05-10 13:48

阿杰_joly | 园豆:112 (初学一级) | 2023-05-10 13:49



我在项目启动时 反射解析DLL,注入相关接口实现,这没问题
但我需要在项目启动之后,我上传一个dll文件,解析反射注入,
上传成功后,我通过查询IServiceCollection的对象 _services.BuildServiceProvider()
是可以查询到我成功注入相关服务,但实际并不起作用

阿杰_joly | 园豆:112 (初学一级) | 2023-05-10 13:54

@阿杰_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);
}
czd890 | 园豆:14488 (专家六级) | 2023-05-10 17:14
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册