日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

【转载】基于ASP.NET Web Application的插件实现,附DEMO

發(fā)布時(shí)間:2025/7/14 asp.net 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转载】基于ASP.NET Web Application的插件实现,附DEMO 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
最近的項(xiàng)目中涉及到Asp.Net擴(kuò)展性,考慮了兩種擴(kuò)展方法,一種是使用Web Services實(shí)現(xiàn),另一種是動(dòng)態(tài)生成代碼然后利用反射來(lái)實(shí)現(xiàn)插件功能。現(xiàn)在網(wǎng)上博客什么的都是用插件的形式來(lái)擴(kuò)展功能的,所以我也打算用插件來(lái)擴(kuò)展asp.net網(wǎng)站的功能。

??? 使用插件機(jī)制來(lái)擴(kuò)展B/S程序,主要需要實(shí)現(xiàn)兩個(gè)功能,首先是動(dòng)態(tài)編譯插件中的C#代碼,然后利用反射來(lái)執(zhí)行插件已經(jīng)編譯的C#代碼。

???

??? 一、動(dòng)態(tài)編譯

??? 插件一般是以xml文件的形式實(shí)現(xiàn)其配置,必須要先讀取插件中的C#代碼才能進(jìn)行動(dòng)態(tài)編譯。

XmlDocument?doc?=?new?XmlDocument();?
try?
{?
????
//獲取插件配置文件?
????doc.Load(Server.MapPath(@"plugins/"?+?strPluginName?+?"/config.xml"));?
}
?
catch?(Exception?e)?
{?
????Response.Write(
"插件載入錯(cuò)誤:"?+?e.ToString());?
????
return;?
}
?
XmlNode?xn?
=?doc.DocumentElement.SelectSingleNode("csharpcode");?
string?code?=?string.Empty;?
if?(xn?!=?null)?
{?
????XmlElement?xe?
=?(XmlElement)xn;?
????
if?(xe.HasAttribute("link"))?
????
{?
XmlDocument?doc?
=?new?XmlDocument();?
try?
{?
????
//獲取插件配置文件?
????doc.Load(Server.MapPath(@"plugins/"?+?strPluginName?+?"/config.xml"));?
}
?
catch?(Exception?e)?
{?
????Response.Write(
"插件載入錯(cuò)誤:"?+?e.ToString());?
????
return;?
}
?
XmlNode?xn?
=?doc.DocumentElement.SelectSingleNode("csharpcode");?
string?code?=?string.Empty;?
if?(xn?!=?null)?
{?
????XmlElement?xe?
=?(XmlElement)xn;?
????
if?(xe.HasAttribute("link"))?
????
{?
using?(?
????????????StreamReader?sr?
=?
????????????????System.IO.File.OpenText(?
????????????????????Path.Combine(?
????????????????????????Server.MapPath(
@"plugins/"?+?strPluginName?+?"/"),?xe.GetAttribute("link")?
????????????????????)?
????????????????)?
?????????)?
????????
{?
????????????code?
=?sr.ReadToEnd();?
????????????sr.Close();?
????????}
?
????}
?
????
else?
????
{?
????????code?
=?xe.InnerText;?
????}
?
}
復(fù)制代碼

?

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

將要被編譯和執(zhí)行的代碼讀入并以字符串方式保存
聲明CSharpCodeProvider對(duì)象實(shí)例
調(diào)用CSharpCodeProvider實(shí)例的CompileAssemblyFromSource方法編譯
用反射生成被生成對(duì)象的實(shí)例(Assembly.CreateInstance
調(diào)用其方法

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

CodeSnippetCompileUnit?unit?=?new?CodeSnippetCompileUnit(code);?
ICodeCompiler?compiler?
=?new?CSharpCodeProvider().CreateCompiler();?
CompilerParameters?para?
=?new?CompilerParameters();?
para.ReferencedAssemblies.Add(
"System.dll");?
para.ReferencedAssemblies.Add(
"System.Data.dll");?
para.ReferencedAssemblies.Add(
"System.XML.dll");?
para.ReferencedAssemblies.Add(
"System.Drawing.dll");?
para.ReferencedAssemblies.Add(
"System.Web.dll");?
para.ReferencedAssemblies.Add(Server.MapPath(
this.Request.ApplicationPath?+?"/bin/PluginDemo.dll"));?
para.GenerateExecutable?
=?false;?
para.OutputAssembly?
=?dllPath;?
?
//編譯結(jié)果?
CompilerResults?cr?=?compiler.CompileAssemblyFromDom(para,?unit);?
if?(cr.Errors.Count?>?0)?
{?
????Response.Write(
"插件安裝失敗,編譯錯(cuò)誤:<br/>");?
????
//遍歷編譯錯(cuò)誤?
????foreach?(System.CodeDom.Compiler.CompilerError?ce?in?cr.Errors)?
????
{?
????????Response.Write(ce.ErrorText?
+?"(文件:"?+?ce.FileName?+?",行號(hào):"?+?ce.Line.ToString()?+?",錯(cuò)誤編號(hào):"?+?ce.ErrorNumber?+?")<br/>");?
????}
?
????
return;?
}
復(fù)制代碼

???? 了解更多的關(guān)于動(dòng)態(tài)編譯的知識(shí)

這里引用了? System.CodeDom和System.CodeDom.Compiler。

讀取插件中的C#代碼并進(jìn)行動(dòng)態(tài)編譯后,要實(shí)現(xiàn)插件功能,就需要執(zhí)行已經(jīng)編譯好的插件的dll中的代碼了。

??? 二、利用反射實(shí)現(xiàn)插件功能

??? 反射的原理這里就不再說(shuō)了,三層架構(gòu)中用的太多了,呵呵。

public?string?GetPluginOutPut(string?strPluginName)?
{?
????
try?
????
{?
????????
//載入插件程序集?
????????System.Xml.XmlDocument?doc?=?new?System.Xml.XmlDocument();?
????????doc.Load(Server.MapPath(
"plugins/installedplugins.xml"));?
?
????????
string?asmName?=?((System.Xml.XmlElement)doc.DocumentElement.SelectSingleNode("plugin[@name='"?+?strPluginName?+?"']")).GetAttribute("assembly");?
?
????????System.Reflection.Assembly?asm?
=?System.Reflection.Assembly.LoadFrom(Server.MapPath(@"plugins/bin/"?+?asmName));?
????????IPlugin?plugin?
=?(IPlugin)asm.CreateInstance("PluginDemo.plugins."?+?strPluginName);?
?
????????
return?plugin.GetOutput(this);?
????}
?
????
catch?(Exception?ex)?
????
{?
????????
return?"插件‘"?+?strPluginName?+?"’載入失敗:"?+?ex.ToString();?
????}
?
}
復(fù)制代碼

?

?忘了說(shuō)一下,要實(shí)現(xiàn)反射,我們需要先在網(wǎng)站中定義好的一個(gè)IPlugin接口

/**////?<summary>?
///?插件接口?
///?</summary>?

public?interface?IPlugin?
{?
????
/**////?<summary>?
????
///?獲取插件輸出的內(nèi)容?
????
///?</summary>?
????
///?<param?name="page">System.Web.UI.Page</param>?
????
///?<returns>字符串</returns>?

????string?GetOutput(Page?page);?
?
????
/**////?<summary>?
????
///?安裝插件時(shí)執(zhí)行的代碼?
????
///?</summary>?
????
///?<param?name="page">System.Web.UI.Page</param>?

????void?Install(Page?page);?
?
????
/**////?<summary>?
????
///?卸載插件時(shí)執(zhí)行的代碼?
????
///?</summary>?
????
///?<param?name="page">System.Web.UI.Page</param>?

????void?Uninstall(Page?page);?
?
????
/**////?<summary>?
????
///?更新插件時(shí)執(zhí)行的代碼?
????
///?</summary>?
????
///?<param?name="page">System.Web.UI.Page</param>?

????void?Update(Page?page);?
}
復(fù)制代碼

?

?

然后所有的插件的C#代碼都繼承自這一個(gè)接口。

還是把我做的DEMO發(fā)上來(lái)吧,講的不好,大家還是看源碼吧,里面都有注釋,呵呵。


下載地址:http://www.box.net/shared/a2ceqq67ts?

總結(jié)

以上是生活随笔為你收集整理的【转载】基于ASP.NET Web Application的插件实现,附DEMO的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。