在开篇以前我想鄙视我本身一下,这个东西根本不须要去写,原本已经有东西去实现了,正如我组长说个人,看的开源项目太少了。其实这个东西彻底能够用ILMerge来解决。函数
而后再说说前言,开发东西久了,总会积累到必定量的Helper或Util,因而都放到一个项目里面一块儿编一个dll,用的时候就方便,但是问题来了,像SQLite这种Helper须要带上它的dll,再多封装几个类,附带的dll就更多了,有时候想单单用一个很简单的Helper,结果还带了一大堆不相干的dll,会不爽,并且有种感受是引用时就单纯一个Common.dll就够了,什么System.Data.SQLite.dll,System.Data.MySql.dll我都不想带,在一次使用内嵌资源时给流我灵感,把这堆dll在编译的时候都放到项目资源中,须要的时候就去加载,这样就好了。学习
单纯这个就用到了内嵌资源使用方面的知识,另一个就是AppDomain对dll加载方面的知识。编码
在使用内嵌资源时,要把资源包含在项目里面,内嵌的资源在属性页面上"生成操做"选择"潜入资源",spa
在编码时要把资源用上,得用流来读取,经过Assembly的GetManifestResourceStream(string name);方法就能够把资源的流获取到,流到了就爱干吗干吗,代码以下code
1 Stream s = null; 2 byte[] dllDatas = null; 3 try 4 { 5 s = Assembly.GetExecutingAssembly().GetManifestResourceStream("ConsoleApplication2.ClassLibrary1.dll"); 6 dllDatas = new byte[s.Length]; 7 s.Read(dllDatas, 0, dllDatas.Length); 8 } 9 catch (Exception ex) 10 { 11 return null; 12 } 13 finally 14 { 15 if (s != null) 16 { 17 s.Close(); 18 s.Dispose(); 19 } 20 }
dll的流拿到流,使用它的地方就在AppDomain的AssemblyResolve事件,当应用程序域加载外部的程序集时,它会默认往两个地方找,第一是往.NET Framework的目录中找,再到应用程序所在目录中找,因此在默认状况下咱们开发的类库都会跟引用程序放到一个目录,而常常用到的System.dll才不须要放到引用程序目录中。那假如须要的dll没办法从这两个地方找到的话,程序会抛出FileNotFoundException异常,这个仍然有办法解决的,其实在抛出FileNotFoundException异常以前,AppDomain会先触发AssemblyResolve事件,这个事件会返回这个没法找到的程序集,返回的程序集为空,才会抛FileNotFoundException异常,只要咱们注册了AssemblyResolve事件,在绑定的方法中把dll从资源中取出来,加载上程序集以后,没法在文件目录中找到的程序集就能够加载到程序域中,程序集中的类能够照常使用blog
代码以下事件
1 AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); 2 3 4 static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 5 { 6 7 Stream s = null; 8 byte[] dllDatas = null; 9 try 10 { 11 s = Assembly.GetExecutingAssembly().GetManifestResourceStream("ConsoleApplication2.ClassLibrary1.dll"); 12 dllDatas = new byte[s.Length]; 13 s.Read(dllDatas, 0, dllDatas.Length); 14 } 15 catch (Exception ex) 16 { 17 return null; 18 } 19 finally 20 { 21 if (s != null) 22 { 23 s.Close(); 24 s.Dispose(); 25 } 26 } 27 Assembly assembly= AppDomain.CurrentDomain.Load(dllDatas); 28 return assembly; 29 }
可是存在一个问题,这个AssemblyResolve事件在封装的Common项目中注册比较合适,但是AssemblyResolve事件应该是主动调用的,而Common里面的类全都是被调用的,我的以为这个AssemlbyResolve事件能够放到Helper类的静态构造函数里面,此外也暂时想不出更好办法,或者这种方式自己不是一个好的方式。资源
后续在开发中也发现一个问题,假如这个Common.dll在别的程序集也是经过AssemblyResolve事件被加载到程序域中的时候,这些在Common.dll里面经过AssemlbyResolve事件加载进来的程序集有问题。此问题还暂时没法解释,估计要学习一下CLR方面的知识。开发