C# 有关Assembly.Unload详解(2)

    此外还有安全方面问题。对普通的 Assembly.Load 来说,载入的 Assembly 是运行在载入者的 evidence 下,而这绝对是一个安全隐患,可能遭受类似 unix 下面通过溢出以 root 权限读写文件的程序来改写系统文件的类似攻击。而单独在一个 AppDomain 中载入 Assembly 就能够单独设置 CAS 权限,降低执行权限。因为 CLR 架构下的四级权限控制机制,最细的粒度只能到 AppDomain。好在据说 Whidbey 会加入对使用不同 evidence 载入 Assembly 的支持。

    通过这些讨论可以看到,Assembly.Unload 对于基于插件模型的程序来说,其语义的存在是很重要的。但在目前和近几个版本来说,通过 AppDomain 来模拟其语义是比较合适的选择,虽然要付出性能和易用性的问题,但能够更大程度上控制功能和安全性等方面因素。长远来说,Assembly.Unload 的实现是完全可行的,Java 中对类的卸载就是最好的例子,前面那些理由实际上都是工作量和复杂度方面的问题,并不存在无法解决的技术问题。

 re: AppDomain and Shadow Copy 4/30/2004 2:34 AM chornbe

You must also encapsulate the loaded assembly into another class, which is loaded by the new appdomain. Here's the code as it's working for me: (I've created a few custom exception types, and you'll notice I had them back - they're not descended from MarshalByRefObject so I can't just throw them from the encapsulated code)

--- cut first class file

using System; using System.Reflection; using System.Collections; namespace Loader{ /* contains assembly loader objects, stored in a hash * and keyed on the .dll file they represent. Each assembly loader * object can be referenced by the original name/path and is used to * load objects, returned as type Object. It is up to the calling class * to cast the object to the necessary type for consumption. * External interfaces are highly recommended!! * */ public class ObjectLoader : IDisposable { // essentially creates a parallel-hash pair setup // one appDomain per loader protected Hashtable domains = new Hashtable(); // one loader per assembly DLL protected Hashtable loaders = new Hashtable(); public ObjectLoader() {/*...*/} public object GetObject( string dllName, string typeName, object[] constructorParms ){ Loader.AssemblyLoader al = null; object o = null; try{ al = (Loader.AssemblyLoader)loaders[ dllName ]; } catch (Exception){} if( al == null ){ AppDomainSetup setup = new AppDomainSetup(); setup.ShadowCopyFiles = "true"; AppDomain domain = AppDomain.CreateDomain( dllName, null, setup ); domains.Add( dllName, domain ); object[] parms = { dllName }; // object[] parms = null; BindingFlags bindings = BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.Public; try{ al = (Loader.AssemblyLoader)domain.CreateInstanceFromAndUnwrap( "Loader.dll", "Loader.AssemblyLoader", true, bindings, null, parms, null, null, null ); } catch (Exception){ throw new AssemblyLoadFailureException(); } if( al != null ){ if( !loaders.ContainsKey( dllName ) ){ loaders.Add( dllName, al ); } else { throw new AssemblyAlreadyLoadedException(); } } else { throw new AssemblyNotLoadedException(); } } if( al != null ){ o = al.GetObject( typeName, constructorParms ); if( o != null && o is AssemblyNotLoadedException ){ throw new AssemblyNotLoadedException(); } if( o == null || o is ObjectLoadFailureException ){ string msg = "Object could not be loaded. Check that type name " + typeName + " and constructor parameters are correct. Ensure that type name " + typeName + " exists in the assembly " + dllName + "."; throw new ObjectLoadFailureException( msg ); } } return o; } public void Unload( string dllName ){ if( domains.ContainsKey( dllName ) ){ AppDomain domain = (AppDomain)domains[ dllName ]; AppDomain.Unload( domain ); domains.Remove( dllName ); } } ~ObjectLoader(){ dispose( false ); } public void Dispose(){ dispose( true ); } private void dispose( bool disposing ){ if( disposing ){ loaders.Clear(); foreach( object o in domains.Keys ){ string dllName = o.ToString(); Unload( dllName ); } domains.Clear(); } } } }

--- end cut

--- cut second class file

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zysfgx.html