Files
hjha-server/GameDAL/ExpressionsParser/InvokeMethod.cs
xiaoou e9616125ce feat: initial commit - HJHA game server full source
6 major server modules (PdkFriendServer/GlobalSever/ServerCore/GameModule/GameNetModule) +
game logic (GameFix/GameDAL/ServerData) +
network layer (NetWorkMessage) +
data layer (ObjectModel) +
utilities (MrWu/Core/Config/CloudAPI/dll) +
adapters (zyxAdapter/base)

.NET 8.0 C# solution, 16 projects, 958 source files
2026-07-07 12:02:15 +08:00

155 lines
4.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Reflection;
namespace ExpressionsParser {
/// <summary>
/// Invoke object's method that is most compatible with provided arguments
/// </summary>
internal class InvokeMethod {
public object TargetObject { get; set; }
public string MethodName { get; set; }
public InvokeMethod(object o, string methodName) {
TargetObject = o;
MethodName = methodName;
}
protected MethodInfo FindMethod(Type[] argTypes) {
if (TargetObject is Type) {
// static method
#if NET40
return ((Type)TargetObject).GetMethod(MethodName, BindingFlags.Static | BindingFlags.Public);
#else
return ((Type)TargetObject).GetRuntimeMethod(MethodName, argTypes);
#endif
}
#if NET40
return TargetObject.GetType().GetMethod(MethodName, argTypes);
#else
return TargetObject.GetType().GetRuntimeMethod(MethodName, argTypes);
#endif
}
protected IEnumerable<MethodInfo> GetAllMethods() {
if (TargetObject is Type) {
#if NET40
return ((Type)TargetObject).GetMethods(BindingFlags.Static | BindingFlags.Public);
#else
return ((Type)TargetObject).GetRuntimeMethods();
#endif
}
#if NET40
return TargetObject.GetType().GetMethods();
#else
return TargetObject.GetType().GetRuntimeMethods();
#endif
}
public object Invoke(object[] args) {
Type[] argTypes = new Type[args.Length];
for (int i = 0; i < argTypes.Length; i++)
argTypes[i] = args[i] != null ? args[i].GetType() : typeof(object);
// strict matching first
MethodInfo targetMethodInfo = FindMethod(argTypes);
// fuzzy matching
if (targetMethodInfo==null) {
var methods = GetAllMethods();
foreach (var m in methods)
if (m.Name==MethodName &&
m.GetParameters().Length == args.Length &&
CheckParamsCompatibility(m.GetParameters(), argTypes, args)) {
targetMethodInfo = m;
break;
}
}
if (targetMethodInfo == null) {
string[] argTypeNames = new string[argTypes.Length];
for (int i=0; i<argTypeNames.Length; i++)
argTypeNames[i] = argTypes[i].Name;
string argTypeNamesStr = String.Join(",",argTypeNames);
throw new MissingMemberException(
(TargetObject is Type ? (Type)TargetObject : TargetObject.GetType()).FullName+"."+MethodName );
}
object[] argValues = PrepareActualValues(targetMethodInfo.GetParameters(),args);
object res = null;
try {
res = targetMethodInfo.Invoke( TargetObject is Type ? null : TargetObject, argValues);
} catch (TargetInvocationException tiEx) {
if (tiEx.InnerException!=null)
throw new Exception(tiEx.InnerException.Message, tiEx.InnerException);
else {
throw;
}
}
return res;
}
internal static bool IsInstanceOfType(Type t, object val) {
#if NET40
return t.IsInstanceOfType(val);
#else
return val!=null && t.GetTypeInfo().IsAssignableFrom(val.GetType().GetTypeInfo());
#endif
}
protected bool CheckParamsCompatibility(ParameterInfo[] paramsInfo, Type[] types, object[] values) {
for (int i=0; i<paramsInfo.Length; i++) {
Type paramType = paramsInfo[i].ParameterType;
var val = values[i];
if (IsInstanceOfType(paramType, val))
continue;
// null and reference types
if (val==null &&
#if NET40
!paramType.IsValueType
#else
!paramType.GetTypeInfo().IsValueType
#endif
)
continue;
// possible autocast between generic/non-generic common types
try {
Convert.ChangeType(val, paramType, System.Globalization.CultureInfo.InvariantCulture);
continue;
} catch { }
//if (ConvertManager.CanChangeType(types[i],paramType))
// continue;
// incompatible parameter
return false;
}
return true;
}
protected object[] PrepareActualValues(ParameterInfo[] paramsInfo, object[] values) {
object[] res = new object[paramsInfo.Length];
for (int i=0; i<paramsInfo.Length; i++) {
if (values[i]==null || IsInstanceOfType( paramsInfo[i].ParameterType, values[i])) {
res[i] = values[i];
continue;
}
try {
res[i] = Convert.ChangeType( values[i], paramsInfo[i].ParameterType, System.Globalization.CultureInfo.InvariantCulture );
continue;
} catch {
throw new InvalidCastException(
String.Format("Invoke method '{0}': cannot convert argument #{1} from {2} to {3}",
MethodName, i, values[i].GetType(), paramsInfo[i].ParameterType));
}
}
return res;
}
}
}