【转载】基于ASP.NET Web Application的插件实现,附DEMO
使用插件机制来扩展B/S程序,主要需要实现两个功能,首先是动态编译插件中的C#代码,然后利用反射来执行插件已经编译的C#代码。
一、动态编译
插件一般是以xml文件的形式实现其配置,必须要先读取插件中的C#代码才能进行动态编译。
try
{
//获取插件配置文件
doc.Load(Server.MapPath(@"plugins/" + strPluginName + "/config.xml"));
}
catch (Exception e)
{
Response.Write("插件载入错误:" + 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("插件载入错误:" + 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;
}
}
.Net为我们提供了很强大的支持来实现这一切我们可以去做的基础,主要应用的两个命名空间是:System.CodeDom.Compiler和Microsoft.CSharp或Microsoft.VisualBasic。另外还需要用到反射来动态执行你的代码。动态编译并执行代码的原理其实在于将提供的源代码交予CSharpCodeProvider来执行编译(其实和CSC没什么两样),如果没有任何编译错误,生成的IL代码会被编译成DLL存放于于内存并加载在某个应用程序域(默认为当前)内并通过反射的方式来调用其某个方法或者触发某个事件等。之所以说它是插件编写的一种方式也正是因为与此,我们可以通过预先定义好的借口来组织和扩展我们的程序并将其交还给主程序去触发。一个基本的动态编译并执行代码的步骤包括:
将要被编译和执行的代码读入并以字符串方式保存
声明CSharpCodeProvider对象实例
调用CSharpCodeProvider实例的CompileAssemblyFromSource方法编译
用反射生成被生成对象的实例(Assembly.CreateInstance
调用其方法
以下代码片段包含了完整的编译和执行过程:
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;
//编译结果
CompilerResults cr = compiler.CompileAssemblyFromDom(para, unit);
if (cr.Errors.Count > 0)
{
Response.Write("插件安装失败,编译错误:<br/>");
//遍历编译错误
foreach (System.CodeDom.Compiler.CompilerError ce in cr.Errors)
{
Response.Write(ce.ErrorText + "(文件:" + ce.FileName + ",行号:" + ce.Line.ToString() + ",错误编号:" + ce.ErrorNumber + ")<br/>");
}
return;
}
了解更多的关于动态编译的知识
这里引用了 System.CodeDom和System.CodeDom.Compiler。
读取插件中的C#代码并进行动态编译后,要实现插件功能,就需要执行已经编译好的插件的dll中的代码了。
二、利用反射实现插件功能
反射的原理这里就不再说了,三层架构中用的太多了,呵呵。
{
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();
}
}
忘了说一下,要实现反射,我们需要先在网站中定义好的一个IPlugin接口
/// 插件接口
/// </summary>
public interface IPlugin
{
/**//// <summary>
/// 获取插件输出的内容
/// </summary>
/// <param name="page">System.Web.UI.Page</param>
/// <returns>字符串</returns>
string GetOutput(Page page);
/**//// <summary>
/// 安装插件时执行的代码
/// </summary>
/// <param name="page">System.Web.UI.Page</param>
void Install(Page page);
/**//// <summary>
/// 卸载插件时执行的代码
/// </summary>
/// <param name="page">System.Web.UI.Page</param>
void Uninstall(Page page);
/**//// <summary>
/// 更新插件时执行的代码
/// </summary>
/// <param name="page">System.Web.UI.Page</param>
void Update(Page page);
}
然后所有的插件的C#代码都继承自这一个接口。
还是把我做的DEMO发上来吧,讲的不好,大家还是看源码吧,里面都有注释,呵呵。
下载地址:http://www.box.net/shared/a2ceqq67ts
【转载】基于ASP.NET Web Application的插件实现,附DEMO相关推荐
- Creating a LINQ Enabled ASP.NET Web application template using C#.[转]
原文地址:http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/839/Default.aspx 其他相关地址:Building and using a ...
- 基于opencv和pillow实现人脸识别系统(附demo)
更多python教程请到友情连接: 菜鸟教程https://www.piaodoo.com 初中毕业读什么技校 http://cntkd.net 茂名一技http://www.enechn.com p ...
- 手把手教你开发photoshop面板插件(附demo和工具)
手把手教你开发photoshop面板插件(附demo和工具) 一.前言 二.插件演示 三.目录文件介绍 3.1 插件安装 3.2 开启ps开发模式 3.3 插件文件介绍 3.4 manifest 文件 ...
- mysql数据库 web asp.net,使用基于asp.net web的应用程序的mysql数据库
i am getting an error while creating table at run time in c# code,it says, Format of the initializat ...
- 在ASP.NET Web Application 中如何处理图片 【转】-有用
老规矩,直接分析代码 首先是,建立一个表,字段类型是image 通常情况下,你会发现没有办法存image ,因为长度是50,不能改.而一个image通常是1000多个 image数据类型的长度是16, ...
- ASP.NET WEB网站简单入门(简单Demo -发布)
简单分几个阶段 一.简单代码实现 1.新建工程 2.打开设计器(查看设计器),托出一个label ,写上Hello 3.点击调试,即可看到网页效果 4.重新生成后,发布到指定路径下 5.弹出网站发布设 ...
- 基于Unity尝试唇同步/LipSync/OVRLipSync(附Demo及源码)
在视频创作的时候,这个小破站的审核制度有点气人.所以想着写一个工具,以相对较小的成本,尽可能快的加工视频.算是在唇同步技术上的一个小尝试. 目的和初步的想法 基于Unity3D开发语音输入与3D模型开 ...
- 总结ASP.NET MVC Web Application中将数据显示到View中的几种方式
当我们用ASP.NET MVC开发Web应用程序的时候,我们都是将需要呈现的数据通过"Controllers"传输到"View"当中,怎么去实现,下面我介绍一下 ...
- ASP.NET没有魔法——开篇-用VS创建一个ASP.NET Web程序
本文是本系列文章第一篇,主要通过建立一个默认ASP.NET MVC项目来引出与ASP.NET MVC相关的功能,由于ASP.NET MVC一个简单的模板就具备了数据库操作.身份验证.输入数据校验等功能 ...
最新文章
- 条件随机场(CRF) - 2 - 定义和形式
- android wear无法启用,android-wear – 无法创建Android虚拟设备,“没有为此目标安装系统映像”...
- pytorch之卷积模块、池化、激活函数(可视化)
- cnblogs url temp
- nginx反向代理、负载均衡以及分布式下的session保持
- 隐藏1:N关系和工具
- mysql1215_MySQL全面瓦解15:视图
- 简单QT应用到通过手写布局实现QT应用
- GitHub 4.6 万星:Windows Terminal 预览版开放下载!
- python中用于标识字符串的定界符_Python 基本数据类型
- 论文浅尝 | 使用变分推理做KBQA
- 如何将hive查询结果导出成txt文件
- JavaScript | 用户定义函数的一些示例
- 斗鱼上市进行时:将登陆纳斯达克 发行价区间定为11.5至14美元
- python webserver模块,python探索之BaseHTTPServer-实现Web服务器介绍
- 本地拒绝服务漏洞修复建议
- HP服务器固件升级(ILO及bios升级:实操版)
- 盘点软件开发中那些有趣的边际效应
- Android开机自动运行
- python读取千万级数据库数据类型_解决python读取几千万行的大表内存问题