首先我们创建一个接口,用来定义需要new出来的对象有什么方法和属性。
我们简单的定义了一个类,储存一个int变量,一个值刷新的事件委托,一个索引器,还有个相加的方法。
///
/// 准备测试生成的对象
///
[CSharpCallLua]
public interface ICalc
{
int Add(int a);//加法
int Value { get; set; }//对象中储存的一个int值
event Action onValueChanged;//值改变的事件 int返回改变后的值
string this[int index] { get; set; }//索引器,只是为了练习,并没有使用
}
根据我们定义的字段,编写lua对应的代码。
主要实现两个方法,一个是我们定义的Add方法,进行两个数的相加。
另一个是New方法,也就是需要生成的对象的构造器
在构造方法中,我们把第一个参数传给lua的Value字段,第二个参数传给list字段,
list字段对应的是索引器的数组。
另外,因为我们使用了索引器和委托,要实现set_Item,get_Item,add_onValueChanged,remove_onValueChanged方法控制索引器与委托。
而刷新方法refresh是在lua内部调用的。
--元方法
local meta={
__index={
--相加方法
Add=function(self,a)
print("即将执行"..self.Value.."+"..a.."...");
self.Value=self.Value + a;
self.refresh(self,self.Value);
return self.Value;
end,
--索引器添加方法
set_Item=function(self,i,v)
self.list[i]=v;--lua默认索引从1开始
end,
--索引器获取方法
get_Item=function(self,i)
return self.list[i];
end,
--添加监听
add_onValueChanged=function(self,listener)
--如果监听列表不存在,则创建空表作为列表
if self.listeners == nil then
self.listeners = {};
end
table.insert(self.listeners,listener);--添加监听
end,
--撤销监听
remove_onValueChanged=function(self,listener)
for i=1 , #self.listeners do
if CS.System.Object.Equals(self.listeners[i],listener) then
table.remove(i);--撤销监听
break;
end
end
end,
--刷新方法
refresh=function(self,v)
if self.listeners ~= nil then
for i=1 , #self.listeners do
self.listeners[i](v);--把当前的值传回监听方法
end
end
end
}
};
--构造函数
function New(v,strings)
return setmetatable({Value=v,list=strings},meta);
end
剩下的内容利用了之前的文章,简单测试一下,成功创建了C#对象,事件与索引器也是正常的。
using System;
using UnityEngine;
using XLua;
public class InvokeTest : MonoBehaviour
{
///
/// 准备测试生成的对象
///
[CSharpCallLua]
public interface ICalc {
int Add(int a);//加法
int Value { get; set; }//对象中储存的一个int值
event Action onValueChanged;//值改变的事件 int返回改变后的值
string this[int index] { get;set; }//索引器,只是为了练习,并没有使用
}
[CSharpCallLua]
public delegate ICalc GetNew(int value, string[] strings);//用来接收lua中的构造器
private const float gcInterval = 1f;//gc回收间隔 1秒
public TextAsset luaText;//lua脚本
private LuaTable scriptEnv;//脚本的lua环境
private GetNew getNew;//构造器
private void Awake()
{
scriptEnv = LuaEnvExtension.Instance.NewTable();//在主lua环境中创建一个新的表作为当前脚本的环境
LuaTable meta = LuaEnvExtension.Instance.NewTable();//创建一个新的表格存全局变量
meta.Set("__index", LuaEnvExtension.Instance.Global);//获取全局变量作为元方法
scriptEnv.SetMetaTable(meta);//设置meta为当前脚本的元表
meta.Dispose();//回收meta
scriptEnv.Set("self", this);//设置自身
LuaEnvExtension.Instance.DoString(luaText.text, "InvokeTest", scriptEnv);//拷贝lua脚本的方法到scriptEnv中
getNew = scriptEnv.Get("New");//获取构造方法
ICalc testObject = getNew(3,new string[]{"a","b","c"});//利用lua中的构造函数new一个ICalc接口的对象
testObject.onValueChanged += Refresh;//添加监听方法
testObject.Add(2);
Debug.Log(testObject[1]);
}
private void Refresh(int result) {
Debug.Log("相加后的value为:"+result);
}
private void Update()
{
//检测是否满足gc回收条件
if (Time.time - LuaEnvExtension.lastGCTime > gcInterval)
{
LuaEnvExtension.Instance.GC();
LuaEnvExtension.lastGCTime = Time.time;
}
}
private void OnDestroy()
{
//回收内存
getNew = null;
scriptEnv.Dispose();
}
}
public static class LuaEnvExtension
{
public static float lastGCTime;//上次回收时间
public static LuaEnv Instance {
get {
return Inner.instance;
}
}
class Inner {
internal readonly static LuaEnv instance = new LuaEnv();//lua环境
}
}
--元方法
local meta={
__index={
--相加方法
Add=function(self,a)
print("即将执行"..self.Value.."+"..a.."...");
self.Value=self.Value + a;
self.refresh(self,self.Value);
return self.Value;
end,
--索引器添加方法
set_Item=function(self,i,v)
self.list[i]=v;--lua默认索引从1开始
end,
--索引器获取方法
get_Item=function(self,i)
return self.list[i];
end,
--添加监听
add_onValueChanged=function(self,listener)
--如果监听列表不存在,则创建空表作为列表
if self.listeners == nil then
self.listeners = {};
end
table.insert(self.listeners,listener);--添加监听
end,
--撤销监听
remove_onValueChanged=function(self,listener)
for i=1 , #self.listeners do
if CS.System.Object.Equals(self.listeners[i],listener) then
table.remove(i);--撤销监听
break;
end
end
end,
--刷新方法
refresh=function(self,v)
if self.listeners ~= nil then
for i=1 , #self.listeners do
self.listeners[i](v);--把当前的值传回监听方法
end
end
end
}
};
--构造函数
function New(v,strings)
return setmetatable({Value=v,list=strings},meta);
end