92 lines
2.6 KiB
C#
92 lines
2.6 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using UnityEngine;
|
|
using Object = UnityEngine.Object;
|
|
|
|
namespace SerializableFunc
|
|
{
|
|
[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 (targetObject == null || string.IsNullOrWhiteSpace(methodName)) return null;
|
|
if (cachedAction == 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();
|
|
}
|
|
|
|
public SerializableAction()
|
|
{
|
|
}
|
|
|
|
public SerializableAction(Action action)
|
|
{
|
|
if (action == null) throw new ArgumentNullException(nameof(action));
|
|
targetObject = action.Target as Object;
|
|
methodName = action.Method.Name;
|
|
cachedAction = action;
|
|
}
|
|
}
|
|
} |