Added serializable action.

This commit is contained in:
2025-11-03 20:34:21 +01:00
parent b0cd87be7d
commit 21b9cdc77c
11 changed files with 125 additions and 51 deletions

View File

@@ -0,0 +1,98 @@
using System;
using System.Linq;
using System.Reflection;
using UnityEngine;
using Object = UnityEngine.Object;
namespace SerializableFunc.Runtime
{
[Serializable]
public abstract class SerializableFuncBase<TFuncType>
where TFuncType : Delegate
{
[SerializeField] protected 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 (func == null)
{
if (targetObject == null)
{
throw new ArgumentNullException("Target Object is null!");
}
if (string.IsNullOrWhiteSpace(methodName))
{
throw new ArgumentNullException("Target Method is 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;
}
}
}