加入收藏 | 设为首页 | 会员中心 | 我要投稿 焦作站长网 (https://www.0391zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > Asp教程 > 正文

.NET 动态编译

发布时间:2020-03-12 16:16:21 所属栏目:Asp教程 来源:站长网
导读:代码的动态编译并执行是一个.NET平台提供给我们的很强大的工具用以灵活扩展(当然是面对内部开发人员)复杂而无法估算的逻辑,并通过一些额外的代码来扩展我们已

换句话来讲就是将对象加载到另外一个AppDomain中并通过远程调用的方法来调用。所谓远程调用其实也就是跨应用程序域调用,所以这个对象(动态代码)必须继承于MarshalByRefObject类。为了复用,这个接口被单独提到一个工程中,并提供一个工厂来简化每次的调用操作:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Reflection;

namespace RemoteAccess

{

/// <summary>

/// Interface that can be run over the remote AppDomain boundary.

/// </summary>

public interface IRemoteInterface

{

object Invoke(string lcMethod,object[] Parameters);

}

/// <summary>

/// Factory class to create objects exposing IRemoteInterface

/// </summary>

public class RemoteLoaderFactory : MarshalByRefObject

{

private const BindingFlags bfi = BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance;

public RemoteLoaderFactory() {}

public IRemoteInterface Create( string assemblyFile, string typeName, object[] constructArgs )

{

return (IRemoteInterface) Activator.CreateInstanceFrom(

assemblyFile, typeName, false, bfi, null, constructArgs,

null, null, null ).Unwrap();

}

}       

}

 

接下来在原来基础上需要修改的是:

·         将编译成的DLL保存到磁盘中。

·         创建另外的AppDomain。

·         获得IRemoteInterface接口的引用。(将生成的DLL加载到额外的AppDomain)

·         调用InvokeMethod方法来远程调用。

·         可以通过AppDomain.Unload()方法卸载程序集。

以下是完整的代码,演示了如何应用这一方案。

//get the code to compile

string strSourceCode = this.txtSource.Text;

//1. Create an addtional AppDomain

AppDomainSetup objSetup = new AppDomainSetup();

objSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;

AppDomain objAppDomain = AppDomain.CreateDomain("MyAppDomain", null, objSetup);

// 1.Create a new CSharpCodePrivoder instance

CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider();

// 2.Sets the runtime compiling parameters by crating a new CompilerParameters instance

CompilerParameters objCompilerParameters = new CompilerParameters();

objCompilerParameters.ReferencedAssemblies.Add("System.dll");

objCompilerParameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");

// Load the remote loader interface

objCompilerParameters.ReferencedAssemblies.Add("RemoteAccess.dll");

// Load the resulting assembly into memory

objCompilerParameters.GenerateInMemory = false;

objCompilerParameters.OutputAssembly = "DynamicalCode.dll";

// 3.CompilerResults: Complile the code snippet by calling a method from the provider

CompilerResults cr = objCSharpCodePrivoder.CompileAssemblyFromSource(objCompilerParameters, strSourceCode);

if (cr.Errors.HasErrors)

{

string strErrorMsg = cr.Errors.Count.ToString() + " Errors:";

for (int x = 0; x < cr.Errors.Count; x++)

{

strErrorMsg = strErrorMsg + "rnLine: " +

cr.Errors[x].Line.ToString() + " - " +

cr.Errors[x].ErrorText;

}

this.txtResult.Text = strErrorMsg;

MessageBox.Show("There were build erros, please modify your code.", "Compiling Error");

return;

}

// 4. Invoke the method by using Reflection

RemoteLoaderFactory factory = (RemoteLoaderFactory)objAppDomain.CreateInstance("RemoteAccess","RemoteAccess.RemoteLoaderFactory").Unwrap();

 

// with help of factory, create a real 'LiveClass' instance

object objObject = factory.Create("DynamicalCode.dll", "Dynamicly.HelloWorld", null);

if (objObject == null)

{

this.txtResult.Text = "Error: " + "Couldn't load class.";

return;

}

// *** Cast object to remote interface, avoid loading type info

IRemoteInterface objRemote = (IRemoteInterface)objObject;

object[] objCodeParms = new object[1];

objCodeParms[0] = "Allan.";

string strResult = (string)objRemote.Invoke("GetTime", objCodeParms);

this.txtResult.Text = strResult;

//Dispose the objects and unload the generated DLLs.

objRemote = null;

AppDomain.Unload(objAppDomain);

 

System.IO.File.Delete("DynamicalCode.dll");

 

对于客户端的输入程序,我们需要继承于MarshalByRefObject类和IRemoteInterface接口,并添加对RemoteAccess程序集的引用。以下为输入:

using System;

using System.Reflection;

using RemoteAccess;

namespace Dynamicly

{

public class HelloWorld : MarshalByRefObject,IRemoteInterface

{

public object Invoke(string strMethod,object[] Parameters)

{

return this.GetType().InvokeMember(strMethod, BindingFlags.InvokeMethod,null,this,Parameters);

}

public string GetTime(string strName)

{

return  "Welcome " + strName + ", Check in at " + System.DateTime.Now.ToString();

}

}

}

 

这样,你可以通过适时的编译,加载和卸载程序集来保证你的程序始终处于一个可控消耗的过程,并且达到了动态编译的目的,而且因为在不同的应用程序域中,让你的本身的程序更加安全和健壮。示例代码下载:

(编辑:焦作站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读