关于C#中动态加载AppDomain的问题
在操作系统中,利用进程可以对正在运行的应用程序进行隔离,每个应用程序被加载到单独的进程中,并为其分配虚拟内存,进程无法直接访问物理内存,只 能通过操作系统将虚拟内存映射到物理内存中,并保证进程之间的物理内存不会重叠,但是进程最大的缺点就是效率问题,尤其是进程的切换开销很大,而进程间不 能共享内存,所以不可能从一个进程通过传递指针给另一个进程。
在.NET中出现了一个新的概念:AppDomain——应用程序域,所有.NET应用程序都需要运行在托管环境中,操作系统能提供的只有进 程,因此.NET程序需要通过AppDomain这个媒介来运行在进程中,同时使用该incheng提供的内存空间,只要是.NET的应用都会运行在某个 AppDomain中。
当我们运行一个.NET应用程序或者运行库宿主时,OS会首先建立一个进程,然后会在进程中加载CLR(这个加载一般是通过调用 _CorExeMain或者_CorBindToRuntimeEx方法来实现),在加载CLR时会创建一个默认的AppDomain,它是CLR的运行 单元,程序的Main方法就是在这里执行,这个默认的AppDomain是唯一且不能被卸载的,当该进程消灭时,默认AppDomain才会随之消失。
一个进程中可以有多个AppDomain,且它们直接是相互隔离的,我们的Assembly是不能单独执行的,它必须被加载到某个AppDomain中,要想卸载一个Assembly就只能卸载其AppDomain。
最近在我所参加的一个项目中要实现这样一个模块:定制一个作业管理器,它可以定时的以不同频率执行某些.Net应用程序或者存储过程,这里的频 率可以是仅一次、每天、每周还是每月进行执行计划的实施,对于调用存储过程没什么好说的,但是调用.Net应用程序的时候就需要考虑如下问题:
一旦Assembly被作业管理器的服务器调用,(比如某个执行计划正好要被执行了),在调用之前会将程序集加载到默认AppDomain,然 后执行,这就有个问题,如果我需要做替换或者删除Assembly等这些操作的时候,由于Assembly已经被默认AppDomain加载,那么对它的 更改肯定是不允许的,它会弹出这样的错误:

除非你关掉作业管理服务器,然后再操作,显然这样做是很不合理的。
2、创建RemoteLoader类,它可以在AppDomain中自由穿越,这就需要继承System.MarshalByRefObject这个 抽象类,这里RemoteLoader如果不继承MarshalByRefObject类则一定会报错(在不同AppDomain间传递对象,该对象必须 是可序列化的)。以RemoteLoader类做为代理来调用待执行的.Net程序。
注意:system.AppDomain 也提供了一种Load 方法,他和Assembly的静态Load 方法不一样,AppDomain的load 方法是一种实例方法,返回的是一个对程序集的引用,Assembly的静态Load 方发将程序集按值封装发回给发出调用的AppDomain.尽量避免使用AppDomain的load 方法。
使用反射创建类型的实例
通过反射可以获取程序集的类型,我们就可以根据获得的程序集类型来创建该类型的新实例,我们可以通过下面的几个方法实现:
1)System.Activator 的CreateInstance方法。该方法返回新对象的引用。2)System.Activator 的createInstanceFrom 与上一个方法类似,不过需要指定类型及其程序集
3)System.Appdomain 的方法:CreateInstance(),CreateInstanceAndUnwrap,CreateInstranceFrom和CreateInstraceFromAndUnwrap
4)System.type的InvokeMember实例方法:这个方法返回一个与传入参数相符的构造函数,并构造该类型。
5)System.reflection.Constructinfo 的Invoke实例方法
浙公网安备 33010602011771号