125 lines
4.1 KiB
C#
125 lines
4.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
|
|
namespace Upsilon.BaseTypes.UserData
|
|
{
|
|
public enum OperatorType
|
|
{
|
|
UnaryPlus,
|
|
UnaryNegation,
|
|
LogicalNot,
|
|
Addition,
|
|
Subtraction,
|
|
Multiplication,
|
|
Division,
|
|
Modulo
|
|
}
|
|
|
|
public class UserDataTypeOperators
|
|
{
|
|
private class OperatorMethod
|
|
{
|
|
public MethodInfo Info { get; }
|
|
public int[] ParameterTypeHashes { get; }
|
|
|
|
public OperatorMethod(MethodInfo info)
|
|
{
|
|
Info = info;
|
|
ParameterTypeHashes = info.GetParameters().Select(x => x.ParameterType.GetHashCode()).ToArray();
|
|
}
|
|
}
|
|
|
|
private readonly Dictionary<OperatorType, List<OperatorMethod>> _operatorMethods;
|
|
|
|
public UserDataTypeOperators(IReflect t)
|
|
{
|
|
var staticMethod = t.GetMethods(BindingFlags.Static | BindingFlags.Public);
|
|
_operatorMethods = new Dictionary<OperatorType, List<OperatorMethod>>();
|
|
foreach (var methodInfo in staticMethod)
|
|
{
|
|
switch (methodInfo.Name)
|
|
{
|
|
// Unary
|
|
case "op_UnaryPlus":
|
|
LoadMethod(OperatorType.UnaryPlus, methodInfo);
|
|
break;
|
|
case "op_UnaryNegation":
|
|
LoadMethod(OperatorType.UnaryNegation, methodInfo);
|
|
break;
|
|
case "op_LogicalNot":
|
|
LoadMethod(OperatorType.LogicalNot, methodInfo);
|
|
break;
|
|
|
|
// Binary
|
|
case "op_Addition":
|
|
LoadMethod(OperatorType.Addition, methodInfo);
|
|
break;
|
|
case "op_Subtraction":
|
|
LoadMethod(OperatorType.Subtraction, methodInfo);
|
|
break;
|
|
case "op_Multiply":
|
|
LoadMethod(OperatorType.Multiplication, methodInfo);
|
|
break;
|
|
case "op_Division":
|
|
LoadMethod(OperatorType.Division, methodInfo);
|
|
break;
|
|
case "op_Modulus":
|
|
LoadMethod(OperatorType.Modulo, methodInfo);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void LoadMethod(OperatorType type, MethodInfo method)
|
|
{
|
|
if (_operatorMethods.TryGetValue(type, out var ls))
|
|
{
|
|
ls.Add(new OperatorMethod(method));
|
|
}
|
|
else
|
|
{
|
|
_operatorMethods.Add(type, new List<OperatorMethod>(){new OperatorMethod(method)});
|
|
}
|
|
}
|
|
|
|
public MethodInfo GetBinaryOperator(OperatorType op, System.Type t1, System.Type t2)
|
|
{
|
|
if (!_operatorMethods.TryGetValue(op, out var m))
|
|
{
|
|
return null;
|
|
}
|
|
if (t1.IsGenericType) t1 = t1.GetGenericTypeDefinition();
|
|
if (t2.IsGenericType) t2 = t2.GetGenericTypeDefinition();
|
|
|
|
|
|
foreach (var operatorMethod in m)
|
|
{
|
|
if (operatorMethod.ParameterTypeHashes[0] == t1.GetHashCode() &&
|
|
operatorMethod.ParameterTypeHashes[1] == t2.GetHashCode())
|
|
return operatorMethod.Info;
|
|
|
|
if (operatorMethod.ParameterTypeHashes[1] == t2.GetHashCode() &&
|
|
operatorMethod.ParameterTypeHashes[0] == t1.GetHashCode())
|
|
return operatorMethod.Info;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public MethodInfo GetUnaryOperator(OperatorType op, System.Type t1)
|
|
{
|
|
if (!_operatorMethods.TryGetValue(op, out var m))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
foreach (var operatorMethod in m)
|
|
{
|
|
if (operatorMethod.ParameterTypeHashes[0] == t1.GetHashCode())
|
|
return operatorMethod.Info;
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
} |