首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

读取Assembly时怎么不让DLL锁定

2012-10-10 
读取Assembly时如何不让DLL锁定在用Assembly.Load 或者Assembly.Loadfrom读取dll时,dll将被锁定,也就是该

读取Assembly时如何不让DLL锁定

在用Assembly.Load 或者Assembly.Loadfrom读取dll时,dll将被锁定,也就是该程序集无法被更新,修改或删除,下面介绍一下如何获取该程序集并使其不被锁定。

(方法一)

首先会创建出两个类,一个Loader一个是RemoteLoader

说明:
1、Loader类提供创建子程序域和卸载程序域的方法;
2、RemoteLoader类提供装载程序集方法;
3、Loader类获得RemoteLoader类的代理对象,并调用RemoteLoader类的方法;
4、RemoteLoader类的方法在子程序域中完成;
5、Loader类和RemoteLoader类均放在AssemblyLoader.dll程序集文件中;

我们再来看代码:
Loader类:

SetRemoteLoaderObject()方法:

??private AppDomain domain = null;
??private Hashtable domains = new Hashtable();??
??private RemoteLoader rl = null;
读取Assembly时怎么不让DLL锁定public?RemoteLoader?SetRemoteLoaderObject(string?dllName)
读取Assembly时怎么不让DLL锁定{
读取Assembly时怎么不让DLL锁定????AppDomainSetup?setup?=?new?AppDomainSetup();????????????
读取Assembly时怎么不让DLL锁定????setup.ShadowCopyFiles?=?"true";
读取Assembly时怎么不让DLL锁定????domain?=?AppDomain.CreateDomain(dllName,null,setup);
读取Assembly时怎么不让DLL锁定????????????
读取Assembly时怎么不让DLL锁定????domains.Add(dllName,domain);????
读取Assembly时怎么不让DLL锁定????try
读取Assembly时怎么不让DLL锁定????{????????????????rl = (AssemblyLoader.RemoteLoader)domain.CreateInstanceFromAndUnwrap(
????????????????"AssemblyLoader.dll","AssemblyLoader.RemoteLoader");?读取Assembly时怎么不让DLL锁定????????
读取Assembly时怎么不让DLL锁定????}
读取Assembly时怎么不让DLL锁定????catch
读取Assembly时怎么不让DLL锁定????{
读取Assembly时怎么不让DLL锁定????????throw?new?Exception();
读取Assembly时怎么不让DLL锁定????}
读取Assembly时怎么不让DLL锁定}


代码中的变量rl为RemoteLoader类对象,在Loader类中是其私有成员。SetRemoteLoaderObject()方法实际上提供了两个功能,一是创建了子程序域,第二则是获得了RemoteLoader类对象。

请大家一定要注意语句:
rl = (AssemblyLoader.RemoteLoader)domain.CreateInstanceFromAndUnwrap("AssemblyLoader.dll","AssemblyLoader.RemoteLoader");

这条语句就是实现两个程序域之间通讯的关键。因为Loader类是在主程序域中,RemoteLoader类则是在子程序域中。如果我们在Loader类即主程序域中显示实例化RemoteLoader类对象rl,此时调用rl的方法,实际上是在主程序域中调用的。因此,我们必须使用代理的方式,来获得rl对象,这就是CreateInstanceFromAndUnwrap方法的目的。其中参数一为要创建类对象的程序集文件名,参数二则是该类的类型名。

CreateCreateInstanceFromAndUnwrap方法有多个重载。代码中的调用方式是当RemoteLoader类为默认构造函数时的其中一种重载。如果RemoteLoader类的构造函数有参数,则方法应改为:

读取Assembly时怎么不让DLL锁定object[]?parms?=?{dllName};
读取Assembly时怎么不让DLL锁定BindingFlags?bindings?=?BindingFlags.CreateInstance?|
读取Assembly时怎么不让DLL锁定BindingFlags.Instance?|?BindingFlags.Public;
读取Assembly时怎么不让DLL锁定rl?=?(AssemblyLoader.RemoteLoader)domain.CreateInstanceFromAndUnwrap("AssemblyLoader.dll","AssemblyLoader.RemoteLoader",true,bindings,
读取Assembly时怎么不让DLL锁定null,parms,null,null,null);

详细的调用方式可以参考MSDN。

以下Loader类的Unload方法和LoadAssembly方法():

读取Assembly时怎么不让DLL锁定public?Assembly?LoadAssembly(string?dllName)
读取Assembly时怎么不让DLL锁定{
读取Assembly时怎么不让DLL锁定????try
读取Assembly时怎么不让DLL锁定????{
读取Assembly时怎么不让DLL锁定????????SetRemoteLoaderObject(dllName);
读取Assembly时怎么不让DLL锁定????????return?rl.LoadAssembly(dllName);
读取Assembly时怎么不让DLL锁定????}
读取Assembly时怎么不让DLL锁定????catch?(Exception)
读取Assembly时怎么不让DLL锁定????{
读取Assembly时怎么不让DLL锁定????????throw?new?AssemblyLoadFailureException();
读取Assembly时怎么不让DLL锁定????}
读取Assembly时怎么不让DLL锁定}读取Assembly时怎么不让DLL锁定public?void?Unload(string?dllName)
读取Assembly时怎么不让DLL锁定{
读取Assembly时怎么不让DLL锁定????if?(domains.ContainsKey(dllName))
读取Assembly时怎么不让DLL锁定????{
读取Assembly时怎么不让DLL锁定????????AppDomain?appDomain?=?(AppDomain)domains[dllName];
读取Assembly时怎么不让DLL锁定????????AppDomain.Unload(appDomain);
读取Assembly时怎么不让DLL锁定????????domains.Remove(dllName);
读取Assembly时怎么不让DLL锁定????}????????????
读取Assembly时怎么不让DLL锁定}

当我们调用Unload方法时,则程序域domain加载的程序集也将随着而被卸载。LoadAssembly方法中的异常AssemblyLoadFailureException为自定义异常:

读取Assembly时怎么不让DLL锁定????public?class?AssemblyLoadFailureException:Exception
读取Assembly时怎么不让DLL锁定????{
读取Assembly时怎么不让DLL锁定????????public?AssemblyLoadFailureException():base()
读取Assembly时怎么不让DLL锁定????????{????????????
读取Assembly时怎么不让DLL锁定????????}
读取Assembly时怎么不让DLL锁定
读取Assembly时怎么不让DLL锁定????????public?override?string?Message
读取Assembly时怎么不让DLL锁定????????{
读取Assembly时怎么不让DLL锁定????????????get
读取Assembly时怎么不让DLL锁定????????????{
读取Assembly时怎么不让DLL锁定????????????????return?"Assembly?Load?Failure";
读取Assembly时怎么不让DLL锁定????????????}
读取Assembly时怎么不让DLL锁定????????}
读取Assembly时怎么不让DLL锁定
读取Assembly时怎么不让DLL锁定????}


既然在Loader类获得的RemoteLoader类实例必须通过代理的方式,因此该类对象必须支持被序列化。所以我们可以令该类派生MarshalByRefObject。RemoteLoader类的代码:

读取Assembly时怎么不让DLL锁定????public?class?RemoteLoader:MarshalByRefObject
读取Assembly时怎么不让DLL锁定????{
读取Assembly时怎么不让DLL锁定????????public?RemoteLoader(string?dllName)
读取Assembly时怎么不让DLL锁定????????{
读取Assembly时怎么不让DLL锁定????????????if?(assembly?==?null)
读取Assembly时怎么不让DLL锁定????????????{
读取Assembly时怎么不让DLL锁定????????????????assembly?=?Assembly.LoadFrom(dllName);
读取Assembly时怎么不让DLL锁定????????????}
读取Assembly时怎么不让DLL锁定????????}????????
读取Assembly时怎么不让DLL锁定
读取Assembly时怎么不让DLL锁定????????private?Assembly?assembly?=?null;
读取Assembly时怎么不让DLL锁定
读取Assembly时怎么不让DLL锁定????????public?Assembly?LoadAssembly(string?dllName)
读取Assembly时怎么不让DLL锁定????????{
读取Assembly时怎么不让DLL锁定????????????try
读取Assembly时怎么不让DLL锁定????????????{
读取Assembly时怎么不让DLL锁定????????????????assembly?=?Assembly.LoadFrom(dllName);????????????????
读取Assembly时怎么不让DLL锁定????????????????return?assembly;
读取Assembly时怎么不让DLL锁定????????????}
读取Assembly时怎么不让DLL锁定????????????catch?(Exception)
读取Assembly时怎么不让DLL锁定????????????{
读取Assembly时怎么不让DLL锁定????????????????throw?new?AssemblyLoadFailureException();
读取Assembly时怎么不让DLL锁定????????????}
读取Assembly时怎么不让DLL锁定????????}
读取Assembly时怎么不让DLL锁定????}


通过上述的两个类,我们就可以实现程序集的加载和卸载。另外,为了保证应用程序域的对象在内存中被清除,应该令这两个类都实现IDisposable接口,和实现Dispose()方法。

?

在应用时,只需要调用Loader的LoadAssembly方法。

?

(方法二)

只需将该dll 读取到一个字节数组,然后再调用Assembly. Load(),相当于给该dll创建了一个副本。

?

Bye[] content=File.ReadAllBytes(assemblyPath);Assembly assembly=Assembly.Load(content);
?

?

?

热点排行