国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當前位置: 首頁 - 科技 - 知識百科 - 正文

.NET 動態(tài)編譯

來源:懂視網 責編:小采 時間:2020-11-27 22:44:22
文檔

.NET 動態(tài)編譯

.NET 動態(tài)編譯:這在很大程度上給我們提供了另外一種擴展的方式(當然這并不能算是嚴格意義上的擴展,但至少為我們提供了一種思路)。 動態(tài)代碼執(zhí)行可以應用在諸如模板生成,外加邏輯擴展等一些場合。一個簡單的例子,為了網站那的響應速度,HTML靜態(tài)頁面往往是我們最好的選
推薦度:
導讀.NET 動態(tài)編譯:這在很大程度上給我們提供了另外一種擴展的方式(當然這并不能算是嚴格意義上的擴展,但至少為我們提供了一種思路)。 動態(tài)代碼執(zhí)行可以應用在諸如模板生成,外加邏輯擴展等一些場合。一個簡單的例子,為了網站那的響應速度,HTML靜態(tài)頁面往往是我們最好的選

這在很大程度上給我們提供了另外一種擴展的方式(當然這并不能算是嚴格意義上的擴展,但至少為我們提供了一種思路)。

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

 

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

 

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

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

·         聲明CSharpCodeProvider對象實例

·         調用CSharpCodeProvider實例的CompileAssemblyFromSource方法編譯

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

·         調用其方法

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

//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ù)時設置了GenerateInMemory為true,這表明生成的DLL會被加載在內存中(隨后被默認引用入當前應用程序域)。在調用GetTime方法時我們需要加入參數(shù),傳遞object類型的數(shù)組并通過Reflection的InvokeMember來調用。在創(chuàng)建生成的Assembly中的對象實例時,需要注意用到的命名空間是你輸入代碼的真實命名空間。以下是我們輸入的測試代碼(為了方便,所有的代碼都在外部輸入,動態(tài)執(zhí)行時不做調整):

using System;

 

namespace Dynamicly

{

    public class HelloWorld

    {

        public string GetTime(string strName)

        {

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

        }

    }

}

運行附件中提供的程序,可以很容易得到一下結果:

 

改進的執(zhí)行過程

 

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

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

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

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

·         創(chuàng)建一個公共的遠程調用接口

·         創(chuàng)建遠程調用接口的實例。并通過這個接口來訪問其方法。

換句話來講就是將對象加載到另外一個AppDomain中并通過遠程調用的方法來調用。所謂遠程調用其實也就是跨應用程序域調用,所以這個對象(動態(tài)代碼)必須繼承于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保存到磁盤中。

·         創(chuàng)建另外的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 + "\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程序集的引用。以下為輸入:

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

        }

    }

}

 

這樣,你可以通過適時的編譯,加載和卸載程序集來保證你的程序始終處于一個可控消耗的過程,并且達到了動態(tài)編譯的目的,而且因為在不同的應用程序域中,讓你的本身的程序更加安全和健壯。示例代碼下載:
http://xiazai.jb51.net/200905/yuanma/DynamicCompiler.rar

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

.NET 動態(tài)編譯

.NET 動態(tài)編譯:這在很大程度上給我們提供了另外一種擴展的方式(當然這并不能算是嚴格意義上的擴展,但至少為我們提供了一種思路)。 動態(tài)代碼執(zhí)行可以應用在諸如模板生成,外加邏輯擴展等一些場合。一個簡單的例子,為了網站那的響應速度,HTML靜態(tài)頁面往往是我們最好的選
推薦度:
標簽: 動態(tài) net 編譯
  • 熱門焦點

最新推薦

猜你喜歡

熱門推薦

專題
Top
主站蜘蛛池模板: 亚洲国产欧美日韩精品一区二区三区 | a一级毛片免费播放 | 欧美区国产区 | 久久国产欧美日韩高清专区 | 久久久久亚洲精品成人网小说 | 欧美一区二区三区视频 | 爱啪网亚洲第一福利网站 | 国产日韩欧美视频在线 | 欧美 日韩 高清 | 中日韩一区二区三区 | 日本一区二区三区在线播放 | 国产未成女年一区二区 | 国产一区二区久久久 | 日韩欧美高清视频 | 91社区在线观看精品 | 精品一区二区免费视频 | 亚洲欧美日韩中文v在线 | 国产精品香蕉在线观看 | 日本高清一区二区三区不卡免费 | 国产未成女年一区二区 | 国产黑色丝袜一区在线 | 一区二区三区久久 | 亚洲欧美日韩精品高清 | 国内一区二区三区精品视频 | 国产九区 | 免费国产最新进精品视频 | 欧美日韩精品在线 | 久久国产精品一区二区 | 一级毛片在线看在线播放 | 天堂精品高清1区2区3区 | 久久综合精品国产一区二区三区无 | 国产视频一区二区在线播放 | 图片亚洲va欧美va国产综合 | 羞羞色院91精品网站 | 精品国产一区二区三区久久影院 | 91中文字幕在线视频 | 亚洲一区二区三区在线播放 | 免费观看a毛片一区二区不卡 | 最新国产精品电影入口 | 欧美日韩免费在线视频 | 亚洲成人777|