90 lines
2.7 KiB
C#
90 lines
2.7 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using UnityEngine;
|
|
|
|
namespace SerializableFunc.Runtime
|
|
{
|
|
[Serializable]
|
|
public abstract class SerializableFuncBase<TFuncType> where TFuncType : Delegate
|
|
{
|
|
[SerializeField] protected UnityEngine.Object targetObject;
|
|
[SerializeField] protected string methodName;
|
|
|
|
private TFuncType func;
|
|
|
|
private static BindingFlags SuitableMethodsFlags =
|
|
BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance;
|
|
|
|
public UnityEngine.Object TargetObject
|
|
{
|
|
get => targetObject;
|
|
set => targetObject = value;
|
|
}
|
|
|
|
public string MethodName
|
|
{
|
|
get => methodName;
|
|
set => methodName = value;
|
|
}
|
|
|
|
protected TFuncType GetReturnedFunc()
|
|
{
|
|
if (targetObject == null || string.IsNullOrWhiteSpace(methodName)) return null;
|
|
if (func == null)
|
|
{
|
|
Type funcType = typeof(TFuncType);
|
|
|
|
MethodInfo info = targetObject
|
|
.GetType()
|
|
.GetMethods(SuitableMethodsFlags)
|
|
.FirstOrDefault(x => IsTargetMethodInfo(x, funcType));
|
|
|
|
if (info == null)
|
|
{
|
|
throw new MissingMethodException(
|
|
$"Object \"{targetObject.name}\" is missing target method: {methodName}"
|
|
);
|
|
}
|
|
|
|
func = (TFuncType)Delegate.CreateDelegate(funcType, targetObject, methodName);
|
|
}
|
|
|
|
return func;
|
|
}
|
|
|
|
#region Utility Functions
|
|
|
|
private bool IsTargetMethodInfo(MethodInfo methodInfo, Type funcType)
|
|
{
|
|
if (!string.Equals(methodInfo.Name, methodName, StringComparison.InvariantCulture)) return false;
|
|
|
|
Type[] typeArguments = funcType.GetGenericArguments();
|
|
|
|
if (methodInfo.ReturnType != typeArguments.Last()) return false;
|
|
|
|
ParameterInfo[] parameters = methodInfo.GetParameters();
|
|
|
|
if (parameters.Length != (typeArguments.Length - 1)) return false;
|
|
|
|
for (int i = 0; i < parameters.Length; i++)
|
|
{
|
|
Type argType = typeArguments[i];
|
|
ParameterInfo parameterInfo = parameters[i];
|
|
if (argType != parameterInfo.ParameterType) return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
public static implicit operator TFuncType(SerializableFuncBase<TFuncType> func)
|
|
{
|
|
if (func == null) return null;
|
|
|
|
TFuncType result = func.GetReturnedFunc();
|
|
return result;
|
|
}
|
|
}
|
|
} |