真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

.NET中的動(dòng)態(tài)編譯技術(shù)是什么-創(chuàng)新互聯(lián)

這篇文章給大家介紹.NET中的動(dòng)態(tài)編譯技術(shù)是什么,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、淮濱網(wǎng)絡(luò)推廣、成都微信小程序、淮濱網(wǎng)絡(luò)營銷、淮濱企業(yè)策劃、淮濱品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們大的嘉獎(jiǎng);創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供淮濱建站搭建服務(wù),24小時(shí)服務(wù)熱線:13518219792,官方網(wǎng)址:www.cdcxhl.com

代碼的動(dòng)態(tài)編譯并執(zhí)行是一個(gè).NET平臺(tái)提供給我們的很強(qiáng)大的工具用以靈活擴(kuò)展(當(dāng)然是面對內(nèi)部開發(fā)人員)復(fù)雜而無法估算的邏輯,并通過一些額外的代碼來擴(kuò)展我們已有 的應(yīng)用程序。這在很大程度上給我們提供了另外一種擴(kuò)展的方式(當(dāng)然這并不能算是嚴(yán)格意義上的擴(kuò)展,但至少為我們提供了一種思路)。

動(dòng)態(tài)代碼執(zhí)行可以應(yīng)用在諸如模板生成,外加邏輯擴(kuò)展等一些場合。一個(gè)簡單的例子,為了網(wǎng)站那的響應(yīng)速度,HTML靜態(tài)頁面往往是我們好的選擇,但基于數(shù)據(jù)驅(qū)動(dòng)的網(wǎng)站往往又很難用靜態(tài)頁面實(shí)現(xiàn),那么將動(dòng)態(tài)頁面生成html的工作或許就是一個(gè)很好的應(yīng)用場合。另外,對于一些模板的套用,我們同樣可以用它來做。另外這本身也是插件編寫的方式。

最基本的動(dòng)態(tài)編譯

.Net為我們提供了很強(qiáng)大的支持來實(shí)現(xiàn)這一切我們可以去做的基礎(chǔ),主要應(yīng)用的兩個(gè)命名空間是:System.CodeDom.Compiler和Microsoft.CSharp或Microsoft.VisualBasic。另外還需要用到反射來動(dòng)態(tài)執(zhí)行你的代碼。動(dòng)態(tài)編譯并執(zhí)行代碼的原理其實(shí)在于將提供的源代碼交予CSharpCodeProvider來執(zhí)行編譯(其實(shí)和CSC沒什么兩樣),如果沒有任何編譯錯(cuò)誤,生成的IL代碼會(huì)被編譯成DLL存放于于內(nèi)存并加載在某個(gè)應(yīng)用程序域(默認(rèn)為當(dāng)前)內(nèi)并通過反射的方式來調(diào)用其某個(gè)方法或者觸發(fā)某個(gè)事件等。之所以說它是插件編寫的一種方式也正是因?yàn)榕c此,我們可以通過預(yù)先定義好的借口來組織和擴(kuò)展我們的程序并將其交還給主程序去觸發(fā)。一個(gè)基本的動(dòng)態(tài)編譯并執(zhí)行代碼的步驟包括:

·         將要被編譯和執(zhí)行的代碼讀入并以字符串方式保存

·         聲明CSharpCodeProvider對象實(shí)例

·         調(diào)用CSharpCodeProvider實(shí)例的CompileAssemblyFromSource方法編譯

·         用反射生成被生成對象的實(shí)例(Assembly.CreateInstance)

·         調(diào)用其方法

以下代碼片段包含了完整的編譯和執(zhí)行過程:

復(fù)制代碼 代碼如下:


//get the code to compile

string strSourceCode = this.txtSource.Text;

// 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");

objCompilerParameters.GenerateInMemory = true;

// 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 + "\r\nLine: " +

                     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

Assembly objAssembly = cr.CompiledAssembly;

object objClass = objAssembly.CreateInstance("Dynamicly.HelloWorld");

if (objClass == null)

{

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

    return;

}

object[] objCodeParms = new object[1];

objCodeParms[0] = "Allan.";

string strResult = (string)objClass.GetType().InvokeMember(

           "GetTime", BindingFlags.InvokeMethod, null, objClass, objCodeParms);

this.txtResult.Text = strResult;


需要解釋的是,這里我們在傳遞編譯參數(shù)時(shí)設(shè)置了GenerateInMemory為true,這表明生成的DLL會(huì)被加載在內(nèi)存中(隨后被默認(rèn)引用入當(dāng)前應(yīng)用程序域)。在調(diào)用GetTime方法時(shí)我們需要加入?yún)?shù),傳遞object類型的數(shù)組并通過Reflection的InvokeMember來調(diào)用。在創(chuàng)建生成的Assembly中的對象實(shí)例時(shí),需要注意用到的命名空間是你輸入代碼的真實(shí)命名空間。以下是我們輸入的測試代碼(為了方便,所有的代碼都在外部輸入,動(dòng)態(tài)執(zhí)行時(shí)不做調(diào)整):

復(fù)制代碼 代碼如下:


using System;

namespace Dynamicly

{

    public class HelloWorld

    {

        public string GetTime(string strName)

        {

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

        }

    }

}


運(yùn)行附件中提供的程序,可以很容易得到一下結(jié)果:
.NET中的動(dòng)態(tài)編譯技術(shù)是什么

改進(jìn)的執(zhí)行過程

現(xiàn)在一切看起來很好,我們可以編譯代碼并把代碼加載到當(dāng)前應(yīng)用程序域中來參與我們的活動(dòng),但你是否想過去卸載掉這段程序呢?更好的去控制程序呢?另外,當(dāng)你運(yùn)行這個(gè)程序很多遍的時(shí)候,你會(huì)發(fā)現(xiàn)占用內(nèi)存很大,而且每次執(zhí)行都會(huì)增大內(nèi)存使用。是否需要來解決這個(gè)問題呢?當(dāng)然需要,否則你會(huì)發(fā)現(xiàn)這個(gè)東西根本沒用,我需要執(zhí)行的一些大的應(yīng)用會(huì)讓我的服務(wù)器crzay,不堪重負(fù)而瘋掉的。

要解決這個(gè)問題我們需要來了解一下應(yīng)用程序域。.NET Application Domain是.NET提供的運(yùn)行和承載一個(gè)活動(dòng)的進(jìn)程(Process)的容器,它將這個(gè)進(jìn)程運(yùn)行所需的代碼和數(shù)據(jù),隔離到一個(gè)小的范圍內(nèi),稱為Application Domain。當(dāng)一個(gè)應(yīng)用程序運(yùn)行時(shí),Application Domains將所有的程序集/組件集加載到當(dāng)前的應(yīng)用程序域中,并根據(jù)需要來調(diào)用。而對于動(dòng)態(tài)生成的代碼/程序集,我們看起來好像并沒有辦法去管理它。其實(shí)不然,我們可以用Application Domain提供的管理程序集的辦法來動(dòng)態(tài)加載和移除Assemblies來達(dá)到我們的提高性能的目的。具體怎么做呢,在前邊的基礎(chǔ)上增加以下步驟:

·         創(chuàng)建另外一個(gè)Application Domain

·         動(dòng)態(tài)創(chuàng)建(編譯)代碼并保存到磁盤

·         創(chuàng)建一個(gè)公共的遠(yuǎn)程調(diào)用接口

·         創(chuàng)建遠(yuǎn)程調(diào)用接口的實(shí)例。并通過這個(gè)接口來訪問其方法。

換句話來講就是將對象加載到另外一個(gè)AppDomain中并通過遠(yuǎn)程調(diào)用的方法來調(diào)用。所謂遠(yuǎn)程調(diào)用其實(shí)也就是跨應(yīng)用程序域調(diào)用,所以這個(gè)對象(動(dòng)態(tài)代碼)必須繼承于MarshalByRefObject類。為了復(fù)用,這個(gè)接口被單獨(dú)提到一個(gè)工程中,并提供一個(gè)工廠來簡化每次的調(diào)用操作:


復(fù)制代碼 代碼如下:


using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Reflection;

namespace RemoteAccess

{

    ///

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

          ///

          public interface IRemoteInterface

          {

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

          }

          ///

          /// Factory class to create objects exposing IRemoteInterface

          ///

          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();

                   }

          }

}


接下來在原來基礎(chǔ)上需要修改的是:

·         將編譯成的DLL保存到磁盤中。

·         創(chuàng)建另外的AppDomain。

·         獲得IRemoteInterface接口的引用。(將生成的DLL加載到額外的AppDomain)

·         調(diào)用InvokeMethod方法來遠(yuǎn)程調(diào)用。

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

以下是完整的代碼,演示了如何應(yīng)用這一方案。

復(fù)制代碼 代碼如下:


//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 + "\r\nLine: " +

                     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程序集的引用。以下為輸入:

復(fù)制代碼 代碼如下:


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();

        }

    }

}




關(guān)于.NET中的動(dòng)態(tài)編譯技術(shù)是什么就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。


分享標(biāo)題:.NET中的動(dòng)態(tài)編譯技術(shù)是什么-創(chuàng)新互聯(lián)
分享URL:http://weahome.cn/article/degcoh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部