本文參考資料:
1. 《C#高級編程第六版》第十三章:反射
2. rcfalcon的CSDN Blog:《封裝Lua for C#》http://www.BkJia.com/kf/201204/127960.html
本文僅討論什麼是特性定制以及怎樣將C#與LUA腳本配合起來形成我們的應用
using System;
using System.Text;
using System.Reflection;
namespace ConsoleApplication3
{
public class mainClass
{
static void Main(string[] args)
{
Console.WriteLine(GETMYNAME);
Console.Read();
}
[CGYClass("CaiGuangyue")]
public static string GETMYNAME
{
get
{
return "CGY’Name";
}
}
public string CGYComment;
}
[AttributeUsage(AttributeTargets.Property,AllowMultiple=false,Inherited=true)]
class CGYClassAttribute:Attribute
{
private string CGYName;
public CGYClassAttribute(string cgyName)
{
this.CGYName = cgyName;
}
public string GetCGYName()
{
return this.CGYName;
}
}
}
這是我寫的一個測試例子.
.Net FrameWork允許用戶定義自己的特性,如果我們將這些定制特性運用到我們的項目中,那麼當我們開發可擴展應用時,即可加載插件或者模塊,無疑是十分Happy的.
為什麼要提到反射中的定制特性?
因為我們接下來的例子中即將用到特性定制,利用特性定制我們就可以很容易的封裝我們自己的LUA應用,以方便我們在LUA 腳本中使用.
先來一個簡單的例子:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;
using LuaInterface;
namespace LUATest
{
public partial class frmMain : Form
{
private Lua MyLua = new Lua();
private string FileName;
public frmMain()
{
InitializeComponent();
}
private void btnFileName_Click(object sender, EventArgs e)
{
OpenFileDialog ofg=new OpenFileDialog();
ofg.Filter = "LUA腳本文件(*.lua)|*.lua|所有文件(*.*)|*.*";
if (ofg.ShowDialog()==DialogResult.OK)
{
txtFileName.Text = ofg.FileName;
FileName = ofg.FileName;
StreamReader sr = new StreamReader(ofg.FileName,Encoding.Default);
txtFileContent.Text = sr.ReadToEnd();
sr.Close();
}
}
/// <summary>
/// LUA中要用到的Echo方法,目的是將LUA的執行結果msg添加到ListBox txtResult上
/// </summary>
/// <param name="msg">執行結果</param>
public void Echo(string msg)
{
txtResult.Items.Add(msg);
}
private void btnRun_Click(object sender, EventArgs e)
{
MyLua.RegisterFunction("Echo", this, this.GetType().GetMethod("Echo"));
MyLua.DoFile(FileName);
}
}
}
在這個簡單的例子結束後,我們使用反射中的特性定制開始封裝我們自己應用.
定制特性類:
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
namespace LUATest
{
/// <summary>
/// 特性類
/// </summary>
[AttributeUsage(AttributeTargets.Method,AllowMultiple=false,Inherited=false)]
class Lua_ClsAttribute:Attribute
{
private string _luaFuncName;
/// <summary>
/// 特性類構造函數
/// </summary>
public Lua_ClsAttribute(string luaFuncName)
{
this._luaFuncName = luaFuncName;
}
public string GetLuaFuncName()
{
return this._luaFuncName;
}
}
}
我們自己的LUA應用庫:
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Windows;
using LuaInterface;
namespace LUATest
{
/// <summary>
/// 本類采集自rcfalcon的CSDN Blog:《封裝Lua for C#》
/// URL:http://www.BkJia.com/kf/201204/127960.html
/// </summary>
class LUAFrame
{
/// <summary>
/// Lua引擎
/// </summary>
private Lua pLuaVM = new Lua();//lua虛擬機
/// <summary>
/// 注冊lua函數
/// </summary>
/// <param name="pLuaAPIClass">lua函數類</param>
public void BindLuaApiClass(Object pLuaAPIClass)
{
foreach (MethodInfo mInfo in pLuaAPIClass.GetType().GetMethods())
{
foreach (Attribute attr in Attribute.GetCustomAttributes(mInfo))
{
string LuaFunctionName = (attr as Lua_ClsAttribute).GetLuaFuncName();
pLuaVM.RegisterFunction(LuaFunctionName, pLuaAPIClass, mInfo);
}
}
}
/// <summary>
/// 執行lua腳本文件
/// </summary>
/// <param name="luaFileName">腳本文件名</param>
public void ExecuteFile(string luaFileName)
{
pLuaVM.DoFile(luaFileName);
}
/// <summary>
/// 執行lua腳本
/// </summary>
/// <param name="luaCommand">lua指令</param>
public void ExecuteString(string luaCommand)
{
pLuaVM.DoString(luaCommand);
}
}
}
緊接著.構造自己的應用與LUA的API類:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
namespace LUATest
{
class LUAAPI
{
frmMain fm=(frmMain)frmMain.ActiveForm;
/// <summary>
/// LUA中要用到的Echo方法,目的是將LUA的執行結果msg添加到ListBox txtResult上
/// </summary>
/// <param name="msg">執行結果</param>
[Lua_Cls("Echo")]
public void Echo(string msg)
{
fm.EchoResult(msg);
} }
}
接著我們來更改下自己的窗體類:
public partial class frmMain : Form
{
private string FileName;
public frmMain()
{
InitializeComponent();
}
private void btnFileName_Click(object sender, EventArgs e)
{
OpenFileDialog ofg=new OpenFileDialog();
ofg.Filter = "LUA腳本文件(*.lua)|*.lua|所有文件(*.*)|*.*";
if (ofg.ShowDialog()==DialogResult.OK)
{
txtFileName.Text = ofg.FileName;
FileName = ofg.FileName;
StreamReader sr = new StreamReader(ofg.FileName,Encoding.Default);
txtFileContent.Text = sr.ReadToEnd();
sr.Close();
}
}
public void EchoResult(string Msg)
{
txtResult.Items.Add(Msg);
}
private void btnRun_Click(object sender, EventArgs e)
{
LUAFrame lf = new LUAFrame();
lf.BindLuaApiClass(new LUAAPI());
lf.ExecuteFile(FileName);
}
}
LUA文件的內容繼續保持不變,那麼我就可以得到和剛才一樣的輸出結果.