using System;
using System.Linq;
using System.Reflection;
using Chronos.Reflection.Internal;
using UnityEngine;
using UnityObject = UnityEngine.Object;
namespace Chronos.Reflection
{
[Serializable]
public class UnityMethod : UnityMember, ISerializationCallbackReceiver
{
///
/// The underlying reflected method.
///
public MethodInfo methodInfo { get; private set; }
///
/// Whether the reflected method is an extension method.
///
public bool isExtension { get; private set; }
[SerializeField]
private string[] _parameterTypes;
private Type[] __parameterTypes;
///
/// The types of the method's parameters.
///
public Type[] parameterTypes
{
get { return __parameterTypes; }
set { __parameterTypes = value; isReflected = false; }
}
public void OnAfterDeserialize()
{
if (_parameterTypes != null)
{
parameterTypes = _parameterTypes.Select(typeName => TypeSerializer.Deserialize(typeName)).ToArray();
}
}
public void OnBeforeSerialize()
{
if (parameterTypes != null)
{
_parameterTypes = parameterTypes.Select(type => TypeSerializer.Serialize(type)).ToArray();
}
}
#region Constructors
public UnityMethod() { }
public UnityMethod(string name) : base(name) { }
public UnityMethod(string name, UnityObject target) : base(name, target) { }
public UnityMethod(string component, string name) : base(component, name) { }
public UnityMethod(string component, string name, UnityObject target) : base(component, name, target) { }
public UnityMethod(string name, Type[] parameterTypes) : base(name) { this.parameterTypes = parameterTypes; }
public UnityMethod(string name, Type[] parameterTypes, UnityObject target) : this(name, parameterTypes) { this.target = target; Reflect(); }
public UnityMethod(string component, string name, Type[] parameterTypes) : base(component, name) { this.parameterTypes = parameterTypes; }
public UnityMethod(string component, string name, Type[] parameterTypes, UnityObject target) : this(component, name, parameterTypes) { this.target = target; Reflect(); }
#endregion
///
public override void Reflect()
{
EnsureAssigned();
EnsureTargeted();
methodInfo = UnityMemberHelper.ReflectMethod(reflectionTarget, name, parameterTypes);
isExtension = methodInfo.IsExtension();
isReflected = true;
}
///
/// Invokes the method with any number of arguments of any type and returns its return value, or null if there isn't any (void).
///
public object Invoke(params object[] parameters)
{
EnsureReflected();
return UnityMemberHelper.InvokeMethod(reflectionTarget, methodInfo, isExtension, parameters);
}
///
/// Invokes the method with any number of arguments of any type and returns its return value casted to the specified type, or null if there isn't any (void).
///
public T Invoke(params object[] parameters)
{
return (T)Invoke(parameters);
}
///
/// The return type of the reflected method.
///
public Type returnType
{
get
{
EnsureReflected();
return methodInfo.ReturnType;
}
}
public override bool Corresponds(UnityMember other)
{
return
other is UnityMethod &&
base.Corresponds(other) &&
parameterTypes.SequenceEqual(((UnityMethod)other).parameterTypes);
}
}
}