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,83 @@
using System;
using System.Linq;
using System.Reflection;
using UnityEngine;
using Object = UnityEngine.Object;
namespace SerializableFunc.Runtime
{
[Serializable]
public class SerializableAction
{
[SerializeField] private Object targetObject;
[SerializeField] private string methodName;
private Action cachedAction;
private static readonly BindingFlags SuitableMethodsFlags =
BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance;
public Object TargetObject
{
get => targetObject;
set => targetObject = value;
}
public string MethodName
{
get => methodName;
set => methodName = value;
}
private Action GetAction()
{
if (cachedAction == null)
{
if (targetObject == null)
throw new ArgumentNullException(nameof(targetObject), "Target Object is null!");
if (string.IsNullOrWhiteSpace(methodName))
throw new ArgumentNullException(nameof(methodName), "Target Method is null!");
MethodInfo info = targetObject
.GetType()
.GetMethods(SuitableMethodsFlags)
.FirstOrDefault(IsTargetMethodInfo);
if (info == null)
{
throw new MissingMethodException($"Object \"{targetObject.name}\" is missing target void method: {methodName}");
}
cachedAction = (Action)Delegate.CreateDelegate(typeof(Action), targetObject, methodName);
}
return cachedAction;
}
private bool IsTargetMethodInfo(MethodInfo methodInfo)
{
if (!string.Equals(methodInfo.Name, methodName, StringComparison.InvariantCulture))
return false;
if (methodInfo.ReturnType != typeof(void))
return false;
// Only allow parameterless void methods for this version
if (methodInfo.GetParameters().Length != 0)
return false;
return true;
}
public void Invoke()
{
GetAction()?.Invoke();
}
public static implicit operator Action(SerializableAction serializableAction)
{
return serializableAction?.GetAction();
}
}
}