Merge branch 'master' of http://git.newlifex.com/NewLife/X
大石头 编写于 2018-09-25 18:53:17
X
using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using NewLife.Data;
using NewLife.Reflection;

namespace NewLife.Remoting
{
    /// <summary>Api动作</summary>
    public class ApiAction
    {
        /// <summary>动作名称</summary>
        public String Name { get; }

        /// <summary>动作所在类型</summary>
        public Type Type { get; }

        /// <summary>方法</summary>
        public MethodInfo Method { get; }

        /// <summary>控制器对象</summary>
        /// <remarks>如果指定控制器对象,则每次调用前不再实例化对象</remarks>
        public Object Controller { get; set; }

        /// <summary>是否二进制参数</summary>
        public Boolean IsPacketParameter { get; }

        /// <summary>是否二进制返回</summary>
        public Boolean IsPacketReturn { get; }

        /// <summary>实例化</summary>
        public ApiAction(MethodInfo method, Type type)
        {
            if (type == null) type = method.DeclaringType;
            Name = GetName(type, method);

            // 必须同时记录类型和方法,因为有些方法位于继承的不同层次,那样会导致实例化的对象不一致
            Type = type;
            Method = method;

            var ps = method.GetParameters();
            if (ps != null && ps.Length == 1 && ps[0].ParameterType == typeof(Packet)) IsPacketParameter = true;

            if (method.ReturnType == typeof(Packet)) IsPacketReturn = true;
        }

        /// <summary>获取名称</summary>
        /// <param name="type"></param>
        /// <param name="method"></param>
        /// <returns></returns>
        public static String GetName(Type type, MethodInfo method)
        {
            if (type == null) type = method.DeclaringType;
            if (type == null) return null;

            var typeName = type.Name.TrimEnd("Controller");
            var att = type.GetCustomAttribute<ApiAttribute>(true);
            if (att != null) typeName = att.Name;

            var miName = method.Name;
            att = method.GetCustomAttribute<ApiAttribute>();
            if (att != null) miName = att.Name;

            if (typeName.IsNullOrEmpty() || miName.Contains("/"))
                return miName;
            else
                return "{0}/{1}".F(typeName, miName);
        }

        /// <summary>已重载。</summary>
        /// <returns></returns>
        public override String ToString()
        {
            var mi = Method;

            var type = mi.ReturnType;
            var rtype = type.Name;
            if (type.As<Task>())
            {
                if (!type.IsGenericType)
                    rtype = "void";
                else
                {
                    type = type.GetGenericArguments()[0];
                    rtype = type.Name;
                }
            }
            return "{0} {1}({2})".F(rtype, mi.Name, mi.GetParameters().Select(pi => "{0} {1}".F(pi.ParameterType.Name, pi.Name)).Join(", "));
        }
    }
}