## 生成引擎二次开发
xLua的生成引擎支持二次开发,你可以利用它来生成一些文本类型的文件(比如代码,配置等)。xLua本身的link.xml文件的生成就是一个生成引擎插件做的。其它应用场景,比如生成Lua IDE的自动完成配置文件,都可以用这特性来完成。
## 总体介绍
插件需要提供两个东西:1、生成文件的模版;2、一个回调函数,该回调函数接受用户的配置,返回需要注入到模版的数据以及文件的输出流。
## 模版语法
模版语法很简单,只有三种元素:
* eval:语法是<%=exp%>,exp是任意表达式,将计算并以字符串形式输出exp的值;
* code:语法是<% if true then end%>,蓝色部分是任意lua代码,这些代码会执行;
* literal:除eval和code之外其它部分,literal原样输出。
示例:
~~~xml
<%
require "TemplateCommon"
%>
<%ForEachCsList(assembly_infos, function(assembly_info)%>
<%ForEachCsList(assembly_info.Types, function(type)
%>
<%end)%>
<%end)%>
~~~
TemplateCommon有一些预定义的函数可以使用,比如ForEachCsList,可以搜索下工程的TemplateCommon.lua.txt看下有那些函数可以用,就普通的lua而已,你自己写一套也可以。
## API
~~~csharp
public static void CSObjectWrapEditor.Generator.CustomGen(string template_src, GetTasks get_tasks)
~~~
* template_src : 模版的源码;
* get_tasks : 回调函数,类型是GetTasks,用来接受用户的配置,返回需要注入到模版的数据以及文件的输出流;
~~~csharp
public delegate IEnumerable GetTasks(LuaEnv lua_env, UserConfig user_cfg);
~~~
* lua_env : LuaEnv对象,因为返回的模版数据需要放到LuaTable,需要用到LuaEnv.NewTable;
* user_cfg : 用户的配置;
* return : 返回值中,CustomGenTask代表的是一个生成文件,而IEnumerable类型表示同一个模版可以生成多个文件;
~~~csharp
public struct UserConfig
{
public IEnumerable LuaCallCSharp;
public IEnumerable CSharpCallLua;
public IEnumerable ReflectionUse;
}
~~~
~~~csharp
public struct CustomGenTask
{
public LuaTable Data;
public TextWriter Output;
}
~~~
示例:
~~~csharp
public static IEnumerable GetTasks(LuaEnv lua_env, UserConfig user_cfg)
{
LuaTable data = lua_env.NewTable();
var assembly_infos = (from type in user_cfg.ReflectionUse
group type by type.Assembly.GetName().Name into assembly_info
select new { FullName = assembly_info.Key, Types = assembly_info.ToList()}).ToList();
data.Set("assembly_infos", assembly_infos);
yield return new CustomGenTask
{
Data = data,
Output = new StreamWriter(GeneratorConfig.common_path + "/link.xml",
false, Encoding.UTF8)
};
}
~~~
* 这里只生成一个文件,故只返回一个CustomGenTask;
* data就是模版要使用的数据,这里塞了一个assembly_infos字段,这个字段如何使用可以回头看看模版部分;
## 标签
一般来说你可以通过MenuItem开一个菜单来执行触发自定义生成操作,但有时你希望生成操作直接由xLua的“Generate Code”菜单触发,你就需要用到CSObjectWrapEditor.GenCodeMenu
示例:
~~~csharp
[GenCodeMenu]//加到Generate Code菜单里头
public static void GenLinkXml()
{
Generator.CustomGen(ScriptableObject.CreateInstance().Template.text, GetTasks);
}
~~~
ps:以上所有相关代码都在XLua\Src\Editor\LinkXmlGen目录下,也正是文章开头说的link.xml的生成功能的实现。