项目场景:
IOC框架开发使用自定义事件聚合器的发布和订阅,在EventAggregator中定义了ConcurrentDictionary<Type,TEvent> _eventMaps字典,字典中Type均继承了EventBase,在OnExit中发布了一个CloseHardwareEvent事件,在App.Init模块中订阅了CloseHardwareEvent事件,实现了解耦操作
问题描述
当主程序关闭时,触发OnExit事件,事件中执行CloseHardwareEvent操作,发布了事件,按正常逻辑App.Init中订阅事件应该被触发,因为字典中的key确实存在CloseHardwareEvent类型,但实际上并没有触发CloseHardwareMethod
事件发布:
事件订阅:
原因分析:
报警提示:
后发现,CloseHardwareEvent在公共模块中App.Share,主程序和App.Init模块均主动引用了App.Share模块,但App.Init模块是动态加载模块,放在根目录AppModules文件夹中,因为App.Init模块主动引用了App.Share模块,所以App.Share模块也必须放在根目录AppModules文件夹中,这就导致了在实际运行过程中,虽然主模块和App.Init模块引用的是同一个类,但不是从同一个dll中加载的,App.Init模块引用CloseHardwareEvent类型是从根目录AppModules文件夹中的App.Share.dll加载的,但主程序引用的CloseHardwareEvent类型是从根目录中的App.Share.dll加载的,这就出现了虽然ConcurrentDictionary<Type,TEvent> _eventMaps字典中看着是同一个类型,但实际根本就不是同一个dll中加载进来的。才会报以上错误。
此处衍生出另一个问题,也是之前遇到的,因为App.Share也是一个配置类,所有的配置文件全部汇总到此类中,所以其它动态加载的模块需要用到公共参数及配置的话必须引用App.Share模块,因为App.Share模块中有I***ConfigProvider配置提供器,需要在App.Config模块中继承实现,并绑定单例放置到IOC容器中,因为App.Share模块中汇总了Hardware.Motion和Hardware.Camera等硬件配置类,如果App.Share没有放置到根目录AppModules文件夹中,在执行程序时,会报以下错误:
所以当时考虑将App.Share模块放置到主程序根目录和主程序根目录AppModules文件夹中两处,但没想到会出现这种新的问题;
解决方案:
将App.Share模块一分为二,其中的事件聚合器的类型仍然放置到App.Share模块中,将配置文件类放置到新建的App.Config模块中,这样一来,App.Share模块就不需要跟随其它模块放置到根目录AppModules文件夹中,只需要将App.Config模块放置到根目录AppModules文件夹中即可。目前正在测试中
多说两句,用.netFramework框架开发的过程中关于泛型、映射的问题踩了很多的坑,这些问题放到.netCore框架中根本不会出问题,但从事上位机行业,很多第三方库对.netFramework比较友好,没办法,鱼与熊掌不可兼得。。。