xlua学习3 使用lua new一个C#对象

定义对象的属性与方法

首先我们创建一个接口,用来定义需要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代码

根据我们定义的字段,编写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

生成代码

别忘记生成代码,这一步很重要
xlua学习3 使用lua new一个C#对象_第1张图片
生成的代码可以找到
xlua学习3 使用lua new一个C#对象_第2张图片

测试

剩下的内容利用了之前的文章,简单测试一下,成功创建了C#对象,事件与索引器也是正常的。
在这里插入图片描述
xlua学习3 使用lua new一个C#对象_第3张图片

完整代码

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

你可能感兴趣的:(xlua入门)