Fixes to the Type Binder and static method handling
This commit is contained in:
parent
3d9b7a53e9
commit
5646ff1da1
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Upsilon.BaseTypes.Number;
|
||||
using Upsilon.BaseTypes.ScriptFunction;
|
||||
|
@ -71,6 +72,11 @@ namespace Upsilon.BaseTypes
|
|||
}
|
||||
}
|
||||
|
||||
if (o is IEnumerable enumerable)
|
||||
{
|
||||
return new ListUserData(enumerable.Cast<object>().ToList());
|
||||
}
|
||||
|
||||
return new GenericUserData(o);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,78 +25,7 @@ namespace Upsilon.BaseTypes.UserData
|
|||
|
||||
foreach (var match in matches)
|
||||
{
|
||||
var validMatch = true;
|
||||
var parameters = match.GetParameters();
|
||||
for (var i = 0; i < parameters.Length; i++)
|
||||
{
|
||||
var matchParameter = parameters[i];
|
||||
if (args.Length <= i)
|
||||
{
|
||||
if (matchParameter.IsOptional)
|
||||
return match;
|
||||
validMatch = false;
|
||||
break;
|
||||
}
|
||||
var argument = args[i];
|
||||
var argumentType = argument.GetType();
|
||||
|
||||
var typeCode = System.Type.GetTypeCode(matchParameter.ParameterType);
|
||||
switch (typeCode)
|
||||
{
|
||||
case TypeCode.Boolean:
|
||||
if (argument is ScriptBoolean b)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case TypeCode.Char:
|
||||
case TypeCode.String:
|
||||
if (argument is ScriptString s)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case TypeCode.Byte:
|
||||
case TypeCode.Decimal:
|
||||
case TypeCode.Double:
|
||||
case TypeCode.Int16:
|
||||
case TypeCode.Int32:
|
||||
case TypeCode.Int64:
|
||||
case TypeCode.SByte:
|
||||
case TypeCode.Single:
|
||||
case TypeCode.UInt16:
|
||||
case TypeCode.UInt32:
|
||||
case TypeCode.UInt64:
|
||||
if (argument is ScriptNumber numeric)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case TypeCode.Object:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!typeof(ScriptType).IsAssignableFrom(matchParameter.ParameterType) &&
|
||||
argument is IUserData ud)
|
||||
{
|
||||
var csharpType = ud.GetCSharpType();
|
||||
if (matchParameter.ParameterType.IsAssignableFrom(csharpType))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argumentType == typeof(ScriptNull))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!matchParameter.ParameterType.IsAssignableFrom(argumentType))
|
||||
{
|
||||
validMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (validMatch)
|
||||
if (IsValidMatch(match, ref args))
|
||||
return match;
|
||||
}
|
||||
|
||||
|
@ -104,6 +33,83 @@ namespace Upsilon.BaseTypes.UserData
|
|||
return null;
|
||||
}
|
||||
|
||||
public bool IsValidMatch(MethodBase match, ref object[] args)
|
||||
{
|
||||
var validMatch = true;
|
||||
var parameters = match.GetParameters();
|
||||
for (var i = 0; i < parameters.Length; i++)
|
||||
{
|
||||
var matchParameter = parameters[i];
|
||||
if (args.Length <= i)
|
||||
{
|
||||
if (matchParameter.IsOptional)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
var argument = args[i];
|
||||
var argumentType = argument.GetType();
|
||||
|
||||
var typeCode = System.Type.GetTypeCode(matchParameter.ParameterType);
|
||||
switch (typeCode)
|
||||
{
|
||||
case TypeCode.Boolean:
|
||||
if (argument is ScriptBoolean b)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
case TypeCode.Char:
|
||||
case TypeCode.String:
|
||||
if (argument is ScriptString s)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
case TypeCode.Byte:
|
||||
case TypeCode.Decimal:
|
||||
case TypeCode.Double:
|
||||
case TypeCode.Int16:
|
||||
case TypeCode.Int32:
|
||||
case TypeCode.Int64:
|
||||
case TypeCode.SByte:
|
||||
case TypeCode.Single:
|
||||
case TypeCode.UInt16:
|
||||
case TypeCode.UInt32:
|
||||
case TypeCode.UInt64:
|
||||
if (argument is ScriptNumber numeric)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
case TypeCode.Object:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!typeof(ScriptType).IsAssignableFrom(matchParameter.ParameterType) &&
|
||||
argument is IUserData ud)
|
||||
{
|
||||
var csharpType = ud.GetCSharpType();
|
||||
if (matchParameter.ParameterType.IsAssignableFrom(csharpType))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argumentType == typeof(ScriptNull))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!matchParameter.ParameterType.IsAssignableFrom(argumentType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return validMatch;
|
||||
}
|
||||
|
||||
public override object ChangeType(object value, System.Type type, CultureInfo culture)
|
||||
{
|
||||
if (type.IsInstanceOfType(value))
|
||||
|
@ -185,7 +191,40 @@ namespace Upsilon.BaseTypes.UserData
|
|||
if (value is ListUserData d)
|
||||
return d.List;
|
||||
if (value is ScriptTable.ScriptTable table)
|
||||
return table.EvaluationScope.Variables.Select(x => x.Value.ToCSharpObject());
|
||||
{
|
||||
var generics = type.GetGenericArguments();
|
||||
if (generics.Length > 0)
|
||||
{
|
||||
var l1 = typeof(List<>);
|
||||
var requiredListType = l1.MakeGenericType(generics[0]);
|
||||
var list = (IList)Activator.CreateInstance(requiredListType);
|
||||
foreach (var variable in table.EvaluationScope.Variables)
|
||||
{
|
||||
list.Add(variable.Value.ToCSharpObject());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
return table.EvaluationScope.Variables.Select(x => x.Value.ToCSharpObject()).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof(IEnumerable).IsAssignableFrom(type))
|
||||
{
|
||||
if (value is ListUserData d)
|
||||
return d.List;
|
||||
if (value is ScriptTable.ScriptTable table)
|
||||
{
|
||||
var generics = type.GetGenericArguments();
|
||||
var l1 = typeof(List<>);
|
||||
var requiredListType = l1.MakeGenericType(generics[0]);
|
||||
var list = (IList)Activator.CreateInstance(requiredListType);
|
||||
foreach (var variable in table.EvaluationScope.Variables)
|
||||
{
|
||||
list.Add(variable.Value.ToCSharpObject());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
var isScriptTypeRequired = typeof(ScriptType).IsAssignableFrom(type);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using Upsilon.Evaluator;
|
||||
using Upsilon.StandardLibraries;
|
||||
|
@ -73,43 +73,24 @@ namespace Upsilon.BaseTypes.UserData
|
|||
return MethodParts;
|
||||
}
|
||||
|
||||
public MethodInfo GetMethod(ref object[] parameters)
|
||||
public MethodInfo GetMethod(ref object[] arguments)
|
||||
{
|
||||
foreach (var userDataMethodPart in MethodParts)
|
||||
{
|
||||
if (userDataMethodPart.Parameters.Length < parameters.Length)
|
||||
continue;
|
||||
bool valid = true;
|
||||
for (var index = 0; index < userDataMethodPart.Parameters.Length; index++)
|
||||
var methodBase = userDataMethodPart.Method;
|
||||
if (UpsilonBinder.Default.IsValidMatch(methodBase, ref arguments))
|
||||
{
|
||||
var userDataMethodParameter = userDataMethodPart.Parameters[index];
|
||||
if (index >= parameters.Length)
|
||||
var parameters = methodBase.GetParameters();
|
||||
for (var i = 0; i < parameters.Length; i++)
|
||||
{
|
||||
if (userDataMethodParameter.IsOptional)
|
||||
return userDataMethodPart.Method;
|
||||
valid = false;
|
||||
break;
|
||||
var argument = arguments[i];
|
||||
var requiredType = parameters[i].ParameterType;
|
||||
arguments[i] =
|
||||
UpsilonBinder.Default.ChangeType(argument, requiredType, CultureInfo.InvariantCulture);
|
||||
}
|
||||
var parameter = parameters[index];
|
||||
var parameterType = parameter.GetType();
|
||||
if (parameterType.IsGenericType) parameter = parameterType.GetGenericTypeDefinition();
|
||||
if (userDataMethodParameter.Type != parameterType &&
|
||||
!userDataMethodParameter.Type.IsAssignableFrom(parameterType))
|
||||
{
|
||||
if (parameter is ScriptType t)
|
||||
{
|
||||
if (userDataMethodParameter.Type.IsAssignableFrom(t.GetCSharpType()))
|
||||
{
|
||||
parameters[index] = ((ScriptType) parameter).ToCSharpObject();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid) return userDataMethodPart.Method;
|
||||
return methodBase;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
Loading…
Reference in New Issue