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
if (luatype == LuaType.Number)
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[]);
if (netParamIsNumeric)
......
......@@ -275,19 +275,45 @@ namespace NLua.Method
int CallInvokeOnGenericMethod(LuaState luaState, MethodInfo methodToCall, object targetObject)
{
//need to make a concrete type of the generic method definition
var typeArgs = new List<Type>();
ParameterInfo [] parameters = methodToCall.GetParameters();
Dictionary<string, Type> genericParameterNames = new Dictionary<string, Type>();
ParameterInfo[] parameters = methodToCall.GetParameters();
for (int i = 0; i < parameters.Length; i++)
{
ParameterInfo parameter = parameters[i];
if (!parameter.ParameterType.IsGenericParameter)
continue;
if (parameter.ParameterType.IsGenericType)
{
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() };
}
typeArgs.Add(_lastCalledMethod.args[i].GetType());
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]);
}
}
}
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());
var result = concreteMethod.Invoke(targetObject, _lastCalledMethod.args);
......
......@@ -492,6 +492,22 @@ namespace NLuaTest
Assert.AreEqual(true, classWithGenericMethod.GenericMethodSuccess);
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>
/// Normal class containing a generic method
......@@ -35,6 +38,12 @@
_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)
{
return value.Equals(_PassedValue);
......
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