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
This commit is contained in:
154
GameDAL/ExpressionsParser/InvokeMethod.cs
Normal file
154
GameDAL/ExpressionsParser/InvokeMethod.cs
Normal file
@ -0,0 +1,154 @@
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user