知识大全 关于C#中动态加载AppDomain的问题
Posted 知
篇首语:做好自己,不为别人的欣赏而存在,却为着自己的特色而活着。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 关于C#中动态加载AppDomain的问题相关的知识,希望对你有一定的参考价值。
关于C#中动态加载AppDomain的问题 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
在操作系统中 利用进程可以对正在运行的应用程序进行隔离 每个应用程序被加载到单独的进程中 并为其分配虚拟内存 进程无法直接访问物理内存 只能通过操作系统将虚拟内存映射到物理内存中 并保证进程之间的物理内存不会重叠 但是进程最大的缺点就是效率问题 尤其是进程的切换开销很大 而进程间不能共享内存 所以不可能从一个进程通过传递指针给另一个进程 在 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加载 那么对它的更改肯定是不允许的 它会弹出这样的错误 除非你关掉作业管理服务器 然后再操作 显然这样做是很不合理的 并且默认AppDomain是不能被卸载的 那么我们该怎么办呢 我想到的方法是动态的加载Assembly 新建一个AppDomain 让Assembly加载到这个新AppDomain中然后执行 当执行完后卸载这个新的AppDomain即可 方法如下 创建程序集加载类AssemblyDynamicLoader 该类用来创建新的AppDomain 并生成用来执行 Net程序的RemoteLoader类: using System; using System Collections Generic; using System Globalization; using System IO; using System Reflection; using System Text; using Ark Log; /// <summary> /// The local loader /// </summary> public class AssemblyDynamicLoader /// <summary> /// The log util /// </summary> private static ILog log = LogManager GetLogger(typeof(AssemblyDynamicLoader)); /// <summary> /// The new appdomain /// </summary> private AppDomain appDomain; /// <summary> /// The remote loader /// </summary> private RemoteLoader remoteLoader; /// <summary> /// Initializes a new instance of the <see cref= LocalLoader /> class /// </summary> public AssemblyDynamicLoader() AppDomainSetup setup = new AppDomainSetup(); setup ApplicationName = ApplicationLoader ; setup ApplicationBase = AppDomain CurrentDomain BaseDirectory; setup PrivateBinPath = Path Combine(AppDomain CurrentDomain BaseDirectory private ); setup CachePath = setup ApplicationBase; setup ShadowCopyFiles = true ; setup ShadowCopyDirectories = setup ApplicationBase; this appDomain = AppDomain CreateDomain( ApplicationLoaderDomain null setup); String name = Assembly GetExecutingAssembly() GetName() FullName; this remoteLoader = (RemoteLoader)this appDomain CreateInstanceAndUnwrap(name typeof(RemoteLoader) FullName); /// <summary> /// Invokes the method /// </summary> /// <param name= fullName >The full name </param> /// <param name= className >Name of the class </param> /// <param name= argsInput >The args input </param> /// <param name= programName >Name of the program </param> /// <returns>The output of excuting </returns> public String InvokeMethod(String fullName String className String argsInput String programName) this remoteLoader InvokeMethod(fullName className argsInput programName); return this remoteLoader Output; /// <summary> /// Unloads this instance /// </summary> public void Unload() try AppDomain Unload(this appDomain); this appDomain = null; catch (CannotUnloadAppDomainException ex) log Error( To unload assembly error! ex); 创建RemoteLoader类 它可以在AppDomain中自由穿越 这就需要继承System MarshalByRefObject这个抽象类 这里RemoteLoader如果不继承MarshalByRefObject类则一定会报错
(在不同AppDomain间传递对象 该对象必须是可序列化的) 以RemoteLoader类做为代理来调用待执行的 Net程序 using System; using System Collections Generic; using System Globalization; using System IO; using System Reflection; using System Text; /// <summary> /// The Remote loader /// </summary> public class RemoteLoader : MarshalByRefObject /// <summary> /// The assembly we need /// </summary> private Assembly assembly = null; /// <summary> /// The output /// </summary> private String output = String Empty; /// <summary> /// Gets the output /// </summary> /// <value>The output </value> public String Output get return this output; /// <summary> /// Invokes the method /// </summary> /// <param name= fullName >The full name </param> /// <param name= className >Name of the class </param> /// <param name= argsInput >The args input </param> /// <param name= programName >Name of the program </param> public void InvokeMethod(String fullName String className String argsInput String programName) this assembly = null; this output = String Empty; try this assembly = Assembly LoadFrom(fullName); Type pgmType = null; if (this assembly != null) pgmType = this assembly GetType(className true true); else pgmType = Type GetType(className true true); Object[] args = RunJob GetArgs(argsInput); BindingFlags defaultBinding = BindingFlags DeclaredOnly | BindingFlags Public | BindingFlags NonPublic | BindingFlags Instance | BindingFlags IgnoreCase | BindingFlags InvokeMethod | BindingFlags Static; CultureInfo cultureInfo = new CultureInfo( es ES false); try MethodInfo methisInfo = RunJob GetItsMethodInfo(pgmType defaultBinding programName); if (methisInfo == null) this output = EMethod does not exist! ; if (methisInfo IsStatic) if (methisInfo GetParameters() Length == ) if (methisInfo ReturnType == typeof(void)) pgmType InvokeMember(programName defaultBinding null null null cultureInfo); this output = STo call a method without return value successful ; else this output = (String)pgmType InvokeMember(programName defaultBinding null null null cultureInfo); else if (methisInfo ReturnType == typeof(void)) pgmType InvokeMember(programName defaultBinding null null args cultureInfo); this output = STo call a method without return value successful ; else this output = (String)pgmType InvokeMember(programName defaultBinding null null args cultureInfo); else if (methisInfo GetParameters() Length == ) object pgmClass = Activator CreateInstance(pgmType); if (methisInfo ReturnType == typeof(void)) pgmType InvokeMember(programName defaultBinding null pgmClass null cultureInfo); this output = STo call a method without return value successful ; else this output = (String)pgmType InvokeMember(programName defaultBinding null pgmClass null cultureInfo); // ymtpgm is program s name and the return value of it must be started with O else object pgmClass = Activator CreateInstance(pgmType); if (methisInfo ReturnType == typeof(void)) pgmType InvokeMember(programName defaultBinding null pgmClass args cultureInfo); this output = STo call a method without return value successful ; else this output = (String)pgmType InvokeMember(programName defaultBinding null pgmClass args cultureInfo); // ymtpgm is program s name and the return value of it must be started with O catch this output = (String)pgmType InvokeMember(programName defaultBinding null null null cultureInfo); catch (Exception e) this output = E + e Message; 其中的InvokeMethod方法只要提供Assembly的全名 类的全名 待执行方法的输入参数和
cha138/Article/program/net/201311/11489相关参考
ASP.net中动态加载控件时一些问题的总结 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 经常
知识大全 最近QQ空间好友动态显示不完全,总是显示 “数据加载中,请稍候”
最近QQ空间好友动态显示不完全,总是显示“数据加载中,请稍候” 以下文字资料是由(本站网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看
ASP.NET中实现模版的动态加载 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! ASPNET中
首先创建水晶报表rpt文件方法还是采用xsd数据集的方式简便容易操作记得将数据集中的相关字段设为你想要在报表中呈现的字段比如说在内容左边加入一个图片就将相应的图片字段拖放过去能不能直接在水晶报表上
动态库的生成 /*mysumc*/ 复制代码代码如下: #include<stdioh>#includesrch intsum(intaintb)return(a+b);&
<!这里为你提供了三种动态加载js的jquery实例代码哦由于jquery是为用户提供方便的所以利用jquery动态加载文件只要一句话$getscript("testjs");就ok了 &
这里为你提供了三种动态加载js的jquery实例代码哦由于jquery是为用户提供方便的所以利用jquery动态加载文件只要一句话$getScript(\\"testjs\\");就OK了
Nvelocity实现动态加载例子 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 因为工作需要使
这篇文章介绍了gridpanel动态加载数据的实例代码有需要的朋友可以参考一下 复制代码代码如下:cha138/Article/program/Java/JSP/201311/20
Spring动态加载Hibernate映射文件 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nb