Upsilon/Upsilon/BaseTypes/UserData/UserDataMethod.cs

100 lines
3.2 KiB
C#

using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using Upsilon.Evaluator;
using Upsilon.StandardLibraries;
namespace Upsilon.BaseTypes.UserData
{
public class UserDataMethod
{
public class UserDataMethodPart
{
public UserDataMethodPart(MethodInfo method)
{
Method = method;
var pars = method.GetParameters();
Attribute = (ScriptFunctionAttribute) method.GetCustomAttribute(typeof(ScriptFunctionAttribute));
var ls = new List<UserDataMethodParameter>();
foreach (var parameter in pars)
{
if (parameter.ParameterType == typeof(Script))
continue;
if (parameter.ParameterType == typeof(EvaluationScope))
continue;
ls.Add(new UserDataMethodParameter(parameter));
}
Parameters = ls.ToArray();
}
public MethodInfo Method { get; }
public ScriptFunctionAttribute Attribute { get; }
public UserDataMethodParameter[] Parameters { get; }
}
public struct UserDataMethodParameter
{
public UserDataMethodParameter(ParameterInfo info)
{
Type = info.ParameterType;
if (Type.IsGenericType)
Type = Type.GetGenericTypeDefinition();
IsOptional = info.IsOptional;
}
public System.Type Type { get; }
public bool IsOptional { get; }
}
public string Name { get; }
private List<UserDataMethodPart> MethodParts { get; }
public System.Type ReturnType { get; }
public UserDataMethod(MethodInfo method)
{
Name = method.Name;
var part = new UserDataMethodPart(method);
MethodParts = new List<UserDataMethodPart>()
{
part
};
ReturnType = part.Method.ReturnType;
}
public void LoadMethodPart(MethodInfo method)
{
var part = new UserDataMethodPart(method);
MethodParts.Add(part);
}
public List<UserDataMethodPart> GetMethods()
{
return MethodParts;
}
public MethodInfo GetMethod(ref object[] arguments)
{
foreach (var userDataMethodPart in MethodParts)
{
var methodBase = userDataMethodPart.Method;
if (UpsilonBinder.Default.IsValidMatch(methodBase, arguments.Select(x => x.GetType()).ToArray()))
{
var parameters = methodBase.GetParameters();
for (var i = 0; i < parameters.Length; i++)
{
var argument = arguments[i];
var requiredType = parameters[i].ParameterType;
arguments[i] =
UpsilonBinder.Default.ChangeType(argument, requiredType, CultureInfo.InvariantCulture);
}
return methodBase;
}
}
return null;
}
}
}