Skip to content

Commit

Permalink
this[string field]或者this[object field]操作符重载新增get_Item和set_Item调用,用于无法…
Browse files Browse the repository at this point in the history
…添加C#方法时的lua调用。
  • Loading branch information
chexiongsheng committed May 2, 2018
1 parent 4b024fb commit 5535316
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 28 deletions.
13 changes: 11 additions & 2 deletions Assets/XLua/Doc/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,18 @@ end)

## this[string field]或者this[object field]操作符重载为什么在lua无法访问?(比如Dictionary\<string, xxx\>, Dictionary\<object, xxx\>在lua中无法通过dic['abc']或者dic.abc检索值)

在2.1.5~2.1.6版本把这个特性去掉,因为:1、这个特性会导致基类定义的方法、属性、字段等无法访问(比如Animation无法访问到GetComponent方法);2、key为当前类某方法、属性、字段的名字的数据无法检索,比如Dictionary类型,dic['TryGetValue']返回的是一个函数,指向Dictionary的TryGetValue方法。
因为:1、这个特性会导致基类定义的方法、属性、字段等无法访问(比如Animation无法访问到GetComponent方法);2、key为当前类某方法、属性、字段的名字的数据无法检索,比如Dictionary类型,dic['TryGetValue']返回的是一个函数,指向Dictionary的TryGetValue方法。

建议直接方法该操作符的等效方法,比如Dictionary的TryGetValue,如果该方法没有提供,可以在C#那通过Extension method封装一个使用。
如果你的版本大于2.1.11,可以用get_Item来获取值,用set_Item来设置值。要主要只有this[string field]或者this[object field]才有这两个替代api,其它类型的key是没有的。

~~~lua
dic:set_Item('a', 1)
dic:set_Item('b', 2)
print(dic:get_Item('a'))
print(dic:get_Item('b'))
~~~

如果你的版本小于或等于2.1.11,建议直接方法该操作符的等效方法,比如Dictionary的TryGetValue,如果该方法没有提供,可以在C#那通过Extension method封装一个使用。

## 有的Unity对象,在C#为null,在lua为啥不为nil呢?比如一个已经Destroy的GameObject

Expand Down
7 changes: 6 additions & 1 deletion Assets/XLua/Src/CodeEmit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1152,7 +1152,12 @@ public Type EmitTypeWrap(Type toBeWrap)
var instanceMethods = toBeWrap.GetMethods(instanceFlag)
.Concat(extensionMethods == null ? Enumerable.Empty<MethodInfo>() : Utils.GetExtensionMethodsOf(toBeWrap))
.Where(m => Utils.IsSupportedMethod(m))
.Where(m => !m.IsSpecialName).GroupBy(m => m.Name).ToList();
.Where(m => !m.IsSpecialName
|| (
((m.Name == "get_Item" && m.GetParameters().Length == 1) || (m.Name == "set_Item" && m.GetParameters().Length == 2))
&& m.GetParameters()[0].ParameterType.IsAssignableFrom(typeof(string))
)
).GroupBy(m => m.Name).ToList();
var supportOperators = toBeWrap.GetMethods(staticFlag)
.Where(m => m.IsSpecialName && InternalGlobals.supportOp.ContainsKey(m.Name))
.GroupBy(m => m.Name);
Expand Down
7 changes: 6 additions & 1 deletion Assets/XLua/Src/Editor/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,12 @@ static void getClassInfo(Type type, LuaTable parameters)
//warnning: filter all method start with "op_" "add_" "remove_" may filter some ordinary method
parameters.Set("methods", type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.IgnoreCase | BindingFlags.DeclaredOnly)
.Where(method => !method.IsDefined(typeof (ExtensionAttribute), false) || method.GetParameters()[0].ParameterType.IsInterface || method.DeclaringType != type)
.Where(method => !method.IsSpecialName)
.Where(method => !method.IsSpecialName
|| (
((method.Name == "get_Item" && method.GetParameters().Length == 1) || (method.Name == "set_Item" && method.GetParameters().Length == 2))
&& method.GetParameters()[0].ParameterType.IsAssignableFrom(typeof(string))
)
)
.Concat(extension_methods)
.Where(method => !IsDoNotGen(type, method.Name))
.Where(method => !isMethodInBlackList(method) && (!method.IsGenericMethod || extension_methods.Contains(method) || isSupportedGenericMethod(method)) && !isObsolete(method))
Expand Down
12 changes: 11 additions & 1 deletion Assets/XLua/Src/Editor/Template/LuaClassWrap.tpl.txt
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,16 @@ namespace XLua.CSObjectWrap
end
end)%>) <%end%>
{
<%
<%if overload.Name == "get_Item" and overload.IsSpecialName then
local keyType = overload:GetParameters()[0].ParameterType%>
<%=GetCasterStatement(keyType, 2, "key", true)%>;
<%=GetPushStatement(overload.ReturnType, "gen_to_be_invoked[key]")%>;
<%elseif overload.Name == "set_Item" and overload.IsSpecialName then
local keyType = overload:GetParameters()[0].ParameterType
local valueType = overload:GetParameters()[1].ParameterType%>
<%=GetCasterStatement(keyType, 2, "key", true)%>;
<%=GetCasterStatement(valueType, 3, "gen_to_be_invoked[key]")%>;
<% else
in_pos = 0;
ForEachCsList(parameters, function(parameter, pi)
if pi >= real_param_count then return end
Expand Down Expand Up @@ -444,6 +453,7 @@ namespace XLua.CSObjectWrap
<%
end
end)
end
%>
<%if NeedUpdate(type) and not method.IsStatic then%>
<%=GetUpdateStatement(type, 1, "gen_to_be_invoked")%>;
Expand Down
40 changes: 17 additions & 23 deletions Assets/XLua/Src/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,6 @@ static void makeReflectionWrap(RealStatePtr L, Type type, int cls_field, int cls
LuaAPI.lua_rawset(L, is_static ? cls_field : obj_field);
}

Dictionary<string, PropertyInfo> prop_map = new Dictionary<string, PropertyInfo>();
List<PropertyInfo> items = new List<PropertyInfo>();
PropertyInfo[] props = type.GetProperties(flag);
for (int i = 0; i < props.Length; ++i)
Expand All @@ -459,10 +458,6 @@ static void makeReflectionWrap(RealStatePtr L, Type type, int cls_field, int cls
{
items.Add(prop);
}
else
{
prop_map.Add(prop.Name, prop);
}
}

var item_array = items.ToArray();
Expand All @@ -483,14 +478,21 @@ static void makeReflectionWrap(RealStatePtr L, Type type, int cls_field, int cls
continue;
}

PropertyInfo prop = null;
if (method_name.StartsWith("add_") || method_name.StartsWith("remove_")
|| method_name == "get_Item" || method_name == "set_Item")
//indexer
if (method.IsSpecialName && ((method.Name == "get_Item" && method.GetParameters().Length == 1) || (method.Name == "set_Item" && method.GetParameters().Length == 2)))
{
if (!method.GetParameters()[0].ParameterType.IsAssignableFrom(typeof(string)))
{
continue;
}
}

if ((method_name.StartsWith("add_") || method_name.StartsWith("remove_")) && method.IsSpecialName)
{
continue;
}

if (method_name.StartsWith("op_")) // 操作符
if (method_name.StartsWith("op_") && method.IsSpecialName) // 操作符
{
if (InternalGlobals.supportOp.ContainsKey(method_name))
{
Expand All @@ -503,26 +505,18 @@ static void makeReflectionWrap(RealStatePtr L, Type type, int cls_field, int cls
}
continue;
}
else if (method_name.StartsWith("get_") && method.IsSpecialName) // getter of property
else if (method_name.StartsWith("get_") && method.IsSpecialName && method.GetParameters().Length != 1) // getter of property
{
string prop_name = method.Name.Substring(4);
if (!prop_map.TryGetValue(prop_name, out prop))
{
prop = type.GetProperty(prop_name);
}
LuaAPI.xlua_pushasciistring(L, prop.Name);
translator.PushFixCSFunction(L, translator.methodWrapsCache._GenMethodWrap(method.DeclaringType, prop.Name, new MethodBase[] { method }).Call);
LuaAPI.xlua_pushasciistring(L, prop_name);
translator.PushFixCSFunction(L, translator.methodWrapsCache._GenMethodWrap(method.DeclaringType, prop_name, new MethodBase[] { method }).Call);
LuaAPI.lua_rawset(L, method.IsStatic ? cls_getter : obj_getter);
}
else if (method_name.StartsWith("set_") && method.IsSpecialName) // setter of property
else if (method_name.StartsWith("set_") && method.IsSpecialName && method.GetParameters().Length != 2) // setter of property
{
string prop_name = method.Name.Substring(4);
if (!prop_map.TryGetValue(prop_name, out prop))
{
prop = type.GetProperty(prop_name);
}
LuaAPI.xlua_pushasciistring(L, prop.Name);
translator.PushFixCSFunction(L, translator.methodWrapsCache._GenMethodWrap(method.DeclaringType, prop.Name, new MethodBase[] { method }).Call);
LuaAPI.xlua_pushasciistring(L, prop_name);
translator.PushFixCSFunction(L, translator.methodWrapsCache._GenMethodWrap(method.DeclaringType, prop_name, new MethodBase[] { method }).Call);
LuaAPI.lua_rawset(L, method.IsStatic ? cls_setter : obj_setter);
}
else if (method_name == ".ctor" && method.IsConstructor)
Expand Down

0 comments on commit 5535316

Please sign in to comment.