Unverified Commit ded4dc5c authored by yuwei's avatar yuwei Committed by GitHub
Browse files

Added support for generic class parameters for generic methods (#505)

parent 50a963dc
...@@ -117,6 +117,14 @@ namespace NLua ...@@ -117,6 +117,14 @@ namespace NLua
if (luatype == LuaType.Number) if (luatype == LuaType.Number)
return _extractValues[typeof(double)]; return _extractValues[typeof(double)];
} }
//Added support for generic type
if (paramType.IsGenericType)
{
if (luatype == LuaType.UserData)
return _extractValues[typeof(object)];
}
bool netParamIsString = paramType == typeof(string) || paramType == typeof(char[]) || paramType == typeof(byte[]); bool netParamIsString = paramType == typeof(string) || paramType == typeof(char[]) || paramType == typeof(byte[]);
if (netParamIsNumeric) if (netParamIsNumeric)
......
...@@ -275,20 +275,46 @@ namespace NLua.Method ...@@ -275,20 +275,46 @@ namespace NLua.Method
int CallInvokeOnGenericMethod(LuaState luaState, MethodInfo methodToCall, object targetObject) int CallInvokeOnGenericMethod(LuaState luaState, MethodInfo methodToCall, object targetObject)
{ {
//need to make a concrete type of the generic method definition //need to make a concrete type of the generic method definition
var typeArgs = new List<Type>(); Dictionary<string, Type> genericParameterNames = new Dictionary<string, Type>();
ParameterInfo [] parameters = methodToCall.GetParameters();
ParameterInfo[] parameters = methodToCall.GetParameters();
for (int i = 0; i < parameters.Length; i++) for (int i = 0; i < parameters.Length; i++)
{ {
ParameterInfo parameter = parameters[i]; ParameterInfo parameter = parameters[i];
if (!parameter.ParameterType.IsGenericParameter) if (parameter.ParameterType.IsGenericType)
continue; {
var currentArg = _lastCalledMethod.args[i];
var currentArgType = currentArg.GetType();
var genericArgTypeArguments = currentArgType.GenericTypeArguments;
//if currentArgType is array, use element type to be generic arguments for compatibility IEnumerable.
if (currentArgType.IsArray)
{
genericArgTypeArguments = new Type[] { currentArgType.GetElementType() };
}
var genericTypeArguments = parameter.ParameterType.GenericTypeArguments;
for (int j = 0; j < genericTypeArguments.Length; j++)
{
var arg = genericTypeArguments[j];
if (arg.IsGenericParameter && !genericParameterNames.ContainsKey(arg.Name))
{
genericParameterNames.Add(arg.Name, genericArgTypeArguments[j]);
}
}
}
typeArgs.Add(_lastCalledMethod.args[i].GetType()); if (parameter.ParameterType.IsGenericParameter)
{
genericParameterNames.Add(parameter.ParameterType.Name, _lastCalledMethod.args[i].GetType());
}
} }
//Map Name/Type to generic arguments types
var methodGenericArguments = methodToCall.GetGenericArguments();
var typeArgs = methodGenericArguments.Select(item => genericParameterNames[item.Name]);
MethodInfo concreteMethod = methodToCall.MakeGenericMethod(typeArgs.ToArray()); MethodInfo concreteMethod = methodToCall.MakeGenericMethod(typeArgs.ToArray());
var result = concreteMethod.Invoke(targetObject, _lastCalledMethod.args); var result = concreteMethod.Invoke(targetObject, _lastCalledMethod.args);
......
...@@ -492,6 +492,22 @@ namespace NLuaTest ...@@ -492,6 +492,22 @@ namespace NLuaTest
Assert.AreEqual(true, classWithGenericMethod.GenericMethodSuccess); Assert.AreEqual(true, classWithGenericMethod.GenericMethodSuccess);
Assert.AreEqual(56, (classWithGenericMethod.PassedValue as TestTypes.TestClass).val); Assert.AreEqual(56, (classWithGenericMethod.PassedValue as TestTypes.TestClass).val);
lua.RegisterFunction("genericMethod3", classWithGenericMethod, typeof(TestClassWithGenericMethod).GetMethod("GenericMethodWithGenericTypes"));
try
{
lua["ts"] = new string[] { "aaa", "bbb", "ccc" };
lua["dic"] = new Dictionary<string, int> { { "ddd", 111 }, { "eee", 222 }, { "fff", 333 } };
lua.DoString("genericMethod3(ts, dic)");
}
catch
{
}
Assert.AreEqual(true, classWithGenericMethod.GenericMethodSuccess);
Assert.AreEqual(true, classWithGenericMethod.Validate<int>(6));
} }
} }
......
namespace NLuaTest.TestTypes using System.Collections.Generic;
using System.Linq;
namespace NLuaTest.TestTypes
{ {
/// <summary> /// <summary>
/// Normal class containing a generic method /// Normal class containing a generic method
...@@ -35,9 +38,15 @@ ...@@ -35,9 +38,15 @@
_GenericMethodSuccess = true; _GenericMethodSuccess = true;
} }
public void GenericMethodWithGenericTypes<T, T1>(IEnumerable<T> ts, Dictionary<T, T1> dic)
{
_PassedValue = dic.Count() + ts.Count();
_GenericMethodSuccess = true;
}
internal bool Validate<T>(T value) internal bool Validate<T>(T value)
{ {
return value.Equals(_PassedValue); return value.Equals(_PassedValue);
} }
} }
} }
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment