问题描述
有一个Webapi程序,原先将业务逻辑全部封装在一个exe主程序中此程序已经发布并使用。现在,由于业务扩展,需要在原有主程序上增加功能,但可能之后的业务扩展会越来越多因此想考虑是否有一种插件的方式来实现业务扩展。现在基本的想法是这样的1.主程序还是负责http请求的接收,分析接收过来的请求,判断是在主程序中还是在dll中,并将请求进行分发2.当dll收到来自主程序的请求后,完成这个请求的业务逻辑,将结果返回给主程序3.主程序通过现有逻辑将返回内容回复给请求方。现在问题来了1.由于dll只处理业务逻辑,因此希望能与主程序共享一套数据库连接2.由于dll处理业务逻辑,并非完全独立,会使用到主程序中现有的一些业务处理功能,因此需要调用主程序的类或静态方法3.需要动态加载业务插件,希望能在线扩展,不影响原有业务运行。按照上面的内容,各位是否能够帮忙想想实现原理,最好能给出个小的demo,谢谢。
解决方案
解决方案二:
把主程序编成库,插件dll去引用它,这样插件就能用到主程序的代码了主程序如果要调用插件,就在主程序里定义号接口,让插件去实现它最后插件中要有个约定好名称的类/方法,用来做初始化,比如注册实现了接口的类等等,可以在加载插件后由主程序反射调用
解决方案三:
这个架构做出来,再小有DEMO也是一个庞大的系统,很难.
解决方案四:
主程序定义接口,插件继承接口,主程序反射调用
解决方案五:
这个不适用于插件式开发吧,按照业务需求返回的数据可能会稀奇古怪,根本不可能统一,然后你希望逻辑尽可能独立,这不是类似ddd么
解决方案六:
创建一个dll工程如ITest.dll里面publicinterfcaeIPlugin{voidInit(stringstrPluginPath)stringGetPluginName();....//你自己定一吧上面两个是我自己随便写的一般我都会加上上面的两个}然后创建你的插件工程Plugin.dll然后引用上面的ITest.dllusingItest;publicclassYourPlugin:IPlugin{voidInit(stringstrPluginPath){}stringGetPluginName(){regutn"test";}...//实现接口}//然后主程序里面应用ITest.dllpublicIPluginGetPlugin(stringstrFileName/*插件dll绝对路径*/){try{Assemblyasm=Assembly.LoadFile(strFileName);foreach(vartinasm.GetTypes()){if(t.GetInterface("IPlugin")!=null){return(IRegularVul)Activator.CreateInstance(t);}}}catch(ReflectionTypeLoadExceptionex){thrownewReflectionTypeLoadException(ex.Types,ex.LoaderExceptions,ex.Message+"rn"+strFileName);}returnnull;}这个方法加载单个的插件然后把你需要公共访问的代码写到一个dll里面如common.dll然后插件再引用common.dll就是了。。
大概代码就是这样
解决方案七:
没有仔细看你这个问题。随便说一下:.netframework中以mef框架为动态加载插件的基本框架。mef中有动态加载编译到一起的插件的框架,也有可以执行一个文件夹路径而自动查找所有插件的框架。我自己写这方面的东西,因为我写起来比较顺手。但是我建议你先要学习mef,先学习其理念。没有理念而去抄袭什么代码,容易产生邯郸学步的结果。
解决方案八:
引用楼主chatop的回复:
现在问题来了1.由于dll只处理业务逻辑,因此希望能与主程序共享一套数据库连接2.由于dll处理业务逻辑,并非完全独立,会使用到主程序中现有的一些业务处理功能,因此需要调用主程序的类或静态方法3.需要动态加载业务插件,希望能在线扩展,不影响原有业务运行。
这实际上是两个方向的问题,你给搞混了。首先在数据库上,不论是初始工程框架,还是随后创建的、引用了初始工程的框架,它们获得数据库连接的方法都应该只写一次,也就是在初始框架中去写。随后创建的框架由于引用了初始工程,于是可以重复使用它。那么自然地,随后创建的框架早已经在取得数据库链接方面使用到初始工程了,它自然可以使用更多的功能。其实你的问题1和问题2都比较简单初级。你的问题3才刚刚有点机构设计的影子。因为对客户端操作的响应(网关程序)是在初始工程框架中进行解析和处理的,它需要动态加载“将来才逐步增加的插件”,因此需要类似mef那样的概念。所以你的一个工程框架,可以引用初始工程,于是解决了1、2两个问题。而同时它也因此实现了一些初始工程所定义的接口规范,从而可以把自己作为插件注册给初始工程中的运行时代码。
解决方案九:
感谢sp1234,crystal_lz我的目要目的是能尽可能少的改动现有代码而实现插件化扩展目前的向项业务逻辑均以相同的封装进(网关),处理完成后以相同的封装出,所以进出数据结构得有办法控制。按照crystal_lz与sp1234所讲,我必须要将插件共用部分封装成dll供各方调用,这样的话,程序改动有点大,我是想寻求一种能在现有情况下直接共享主程序功能的方法。我现在数据流向是exe:contorler->exe:optClass->exe:dbHelper->exe:contorler我想着,在外部dll中封装出exe:contorler->dll:optClass->exe:dbHelper[dll:dbHelper]->exe->contorler这样的结构在插件被回载和初始化时,将自由的contorler注册到exe中,exe中根据用户请求判断路由到dll中进行处理当dll中发现需要使用exe资源时,可以很方便的调用exe中的资源,处理完成后,将结果返还给exe,并由exe回复给请求者这样做的好处是,我的入口与出口单一,数据层也是单一的,如果有需要,可以在dll中单独建立数据连接,使得业务逻辑相对比较独立,如果配合网络更加容易做分布部署。大家再看看还有没在改动较少的情况下实现这种插件模式的方法?