C#动态编译,实现按钮功能动态配置的代码
把做工程过程比较常用的一些代码片段收藏起来,下面代码段是关于C#动态编译,实现按钮功能动态配置的代码,应该是对小伙伴们有些好处。
using System;
using System.Data;
using System.Configuration;
using System.IO;
using System.Text;
using System.CodeDom.Compiler;
using System.Windows.Forms;
using Microsoft.CSharp;
using System.Reflection;
namespace DynamicAddFunction
{
public class Evaluator
{
private string filepath = Path.Combine(Application.StartupPath, "FunBtn.config");
#region 构造函数
public Evaluator(EvaluatorItem[] items)
{
}
public Evaluator(Type returnType, string expression, string name)
{
EvaluatorItem[] items = { new EvaluatorItem(returnType, expression, name) };
}
public Evaluator(EvaluatorItem item)
{
}
private void ConstructEvaluator(EvaluatorItem[] items)
{
CSharpCodeProvider comp = new CSharpCodeProvider();
CompilerParameters cp = new CompilerParameters();
Configer configer = Configer.Current(filepath);
foreach (var @using in usings)
{
}
{
if (item.ReturnType.Name == "Void")
{
}
else
{
}
}
CompilerResults cr = comp.CompileAssemblyFromSource(cp, code.ToString());
{
{
}
}
}
#endregion
#region 公有成员
public int EvaluateInt(string name)
{
return (int)Evaluate(name);
}
public string EvaluateString(string name)
{
return (string)Evaluate(name);
}
public bool EvaluateBool(string name)
{
return (bool)Evaluate(name);
}
public object Evaluate(string name)
{
}
public void EvaluateVoid(string name)
{
}
#endregion
#region 静态成员
static public int EvaluateToInteger(string code)
{
}
static public string EvaluateToString(string code)
{
}
static public bool EvaluateToBool(string code)
{
}
static public object EvaluateToObject(string code)
{
}
static public void EvaluateToVoid(string code)
{
}
#endregion
#region 私有成员
private const string staticMethodName = "ExecuteBtnCommand";
object _Compiled = null;
#endregion
}
public class EvaluatorItem
{
public Type ReturnType;
public string Expression;
public string Name;
public EvaluatorItem(Type returnType, string expression, string name)
{
ReturnType = returnType;
Expression = expression;
Name = name;
}
}
}
为了提高其灵活性,上面这个类添加的程序集和命名空间,以及调用功能的代码,都改成了读取xml格式的配置文件来获取。这样做理论上可以使得系统中可以添加任意.net制作的dll、exe等的功能。大大增强了系统的灵活性。读写配置文件的类采用了单例模式,可以减少对系统的消耗,代码如下:
using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using System.Xml;
using System.Reflection;
using System.Configuration;
namespace DynamicAddFunction
{
public class Configer
{
#region 私有成员
#endregion
private Configer(string filepath)
{
this.filePath = filepath;
}
public static Configer Current(string filepath)
{
if (current == null)
{
current = new Configer(filepath);
}
return current;
}
public string[] GetAssembly(string path, string nodeProperty)
{
if (!File.Exists(filePath)) return null;
var xmlDoc = new XmlDocument();
xmlDoc.Load(filePath);
string[] assemblies = null;
XmlNodeList nodelist = xmlDoc.SelectNodes(path);
if (nodelist != null)
{
assemblies = new string[nodelist.Count];
{
var element = (XmlElement)nodelist[i];
}
}
}
public string GetNodeProperty(string path, string nodeProperty)
{
XmlDocument doc = new XmlDocument();
doc.Load(filePath);
XmlElement element = null;
element = (XmlElement)(doc.SelectSingleNode(path));
if (element != null)
{
return element.GetAttribute(nodeProperty);
}
else
{
return " ";
}
}
public void SetNodeProperty(string path, string nodeProperty, string nodeValue)
{
var doc = new XmlDocument();
doc.Load(filePath);
XmlElement element = null;
element = (XmlElement)(doc.SelectSingleNode(path));
if (element != null)
{
element.SetAttribute(nodeProperty, nodeValue);
}
doc.Save(filePath);
}
public string GetNodeValue(string path, string nodeProperty)
{
XmlDocument doc = new XmlDocument();
doc.Load(filePath);
XmlNode node = null;
node = (doc.SelectSingleNode(path));
if (node != null)
{
return node.Value;
}
else
{
return " ";
}
}
public void SetNodeValue(string path, string nodeProperty, string nodeValue)
{
var doc = new XmlDocument();
doc.Load(filePath);
XmlNode node = null;
node = (doc.SelectSingleNode(path));
if (node != null)
{
node.Value = nodeValue;
}
doc.Save(filePath);
}
public void SetAllNodeProperty(string path, string nodeProperty, string nodeValue)
{
if (!File.Exists(filePath)) return;
var xmlDoc = new XmlDocument();
xmlDoc.Load(filePath);
var selectSingleNode = xmlDoc.SelectNodes(path);
if (selectSingleNode != null)
{
XmlNodeList nodelist = selectSingleNode;
{
XmlElement element = (XmlElement)VARIABLE;
element.SetAttribute(nodeProperty, nodeValue);
}
}
xmlDoc.Save(filePath);
}
public void CreateNode(string path,string name, string[] nodeProperties, string[] nodeValues)
{
if (!File.Exists(filePath)) return;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(filePath);
var selectSingleNode = xmlDoc.SelectSingleNode(path);
if (selectSingleNode != null)
{
XmlElement xmlElement = xmlDoc.CreateElement(name);
for (int i = 0; i < nodeProperties.Length; i++)
{
xmlElement.SetAttribute(nodeProperties[i], nodeValues[i]);
}
selectSingleNode.AppendChild(xmlElement);
}
}
public void RemoveNode(string path,string name)
{
if (!File.Exists(filePath)) return;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(filePath);
var selectSingleNode = xmlDoc.SelectSingleNode(path);
if (selectSingleNode != null)
{
var node=selectSingleNode.SelectSingleNode(name);
if (node != null)
{
selectSingleNode.RemoveChild(node);
}
}
}
}
}
配置文件信息如下:FunBtn.Config
<?xml version="1.0" encoding="utf-8"?>
<FunBtn>
<!-- 版本信息 -->
<info version="1.00" updatetime="2013-01-01 10:00:00.123" isautoupdate="true" />
<!-- 引用的程序集和命名空间 -->
<assembly>
<dll name="system.dll" />
<dll name="system.data.dll" />
<dll name="system.xml.dll" />
<dll name="system.windows.forms.dll" />
<dll name="FunButton.dll" />
<dll name="DynamicAddFunction.exe" />
<using name="using System;" />
<using name="using System.Data;" />
<using name="using System.Data.SqlClient;" />
<using name="using System.Data.OleDb;" />
<using name="using System.Xml;" />
<using name="using FunButton;" />
<using name="using System.Windows.Forms;" />
<using name="using DynamicAddFunction;" />
</assembly>
<!-- 按钮属性和方法 -->
<btndetail>
<btn name="btnDelOrder" value="删除订单" type="funbtn" rank="0" left="10" top="5" returntype="void" code="new DelOrderBtn().DelOrder(Form1.objs)" />
<btn name="btnCheckOut" value="结 账" type="funbtn" rank="-1" left="10" top="335" returntype="void" code="new CheckOutBtn().CheckOut(Form1.objs)" />
<btn name="btnClose" value="退出" type="funbtn" rank="-1" left="240" top="335" returntype="void" code="Application.Exit()" />
<btn name="btnDelAllOrder" value="整单删除" type="funbtn" rank="-1" left="240" top="225" returntype="void" code="new DelOrderBtn().DelOrder(Form1.objs)" />
<btn name="btnMore" value="更 多" type="funbtn" rank="6" left="10" top="230" returntype="void" code="new frmMore().Show()" />
</btndetail>
</FunBtn>
{-这样在系统调用的时候就可以方便多了(我这里所有的按钮都相应一个事件,即Button_Click事件,它们是通过name,在配置文件中找到对应的代码,然后动态编译,然后去执行的)
--}
public void Button_Click(object sender, EventArgs e)
{
try
{
Configer configer = Configer.Current(filePath);
string code = configer.GetNodeProperty(
string returnType =
"returntype");
switch (returnType)
{
case "void":
Evaluator.EvaluateToVoid(code);
break;
case "object":
Evaluator.EvaluateToObject(code);
break;
case "int":
Evaluator.EvaluateToInteger(code);
break;
case "bool":
Evaluator.EvaluateToBool(code);
break;
case "string":
Evaluator.EvaluateToString(code);
break;
}
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
}
}
这样,只要你配置文件中的加入了程序集和命名控件,且代码OK,那么你就能调用任意的dll了。意味着你拥有了强大的扩展性,在添加功能方面,不用再重新发布新版本了。直接放用到的dll放入到程序根目录下,然后配置正确FunBtn.config即可。当然,其实我还是不推荐用动态编译的,因为影响效率呀。每次点击按钮,都需要重新动态编译,效率肯定是要降低的。所以你在借鉴时,一定要慎重选择哦。

浙公网安备 33010602011771号