예제 #1
0
        /// <summary>
        /// 调用函数
        /// </summary>
        /// <param name="serializer">命令行反序列器</param>
        /// <param name="methodSpecs">函数的参数说明</param>
        /// <param name="obj">调用函数时的this对象</param>
        /// <param name="argList">命令行参数,本集合会被修改,调用完毕后集合内是剩余的命令行参数</param>
        /// <param name="beforeInvoke">获取到函数参数后调用函数前触发</param>
        /// <returns>函数返回值</returns>
        public static object?InvokeMethod(
            CommandLineSerializer serializer,
            MethodSpecs methodSpecs,
            object?obj,
            LinkedList <string> argList,
            Action <ParameterInfo[], object?[]>?beforeInvoke)
        {
            var method         = methodSpecs.Method;
            var paramInfos     = method.GetParameters();
            var length         = paramInfos.Length;
            var parameters     = new object?[length];
            var touchedIndexes = new bool[length];

            serializer.Deserialize(argList, methodSpecs,
                                   (spec, paramObj) =>
            {
                if (methodSpecs.TryGetParameterIndex(spec, out var index) && 0 <= index && index < length)
                {
                    parameters[index]     = paramObj;
                    touchedIndexes[index] = true;
                }
            });

            // 设置函数参数自身的默认值
            for (var i = 0; i < length; ++i)
            {
                var paramInfo = paramInfos[i];
                if (!touchedIndexes[i])
                {
                    if (paramInfo.DefaultValue == DBNull.Value)
                    {
                        throw new InvalidOperationException($"Lack of {i + 1}th non-default parameter: {paramInfo.Name}.");
                    }

                    parameters[i] = paramInfo.DefaultValue;
                }
            }

            beforeInvoke?.Invoke(paramInfos, parameters);

            if (method is ConstructorInfo constructorInfo)
            {
                return(constructorInfo.Invoke(parameters));
            }

            return(method.Invoke(obj, parameters));
        }
        public ObjectSpecs?GetObjectSpecs(Type objType)
        {
            var memberSpecs = new MemberSpecs(objType);

            memberSpecs.Init();

            object?deserializeObj = null;
            object?serializeObj   = null;

            return(new ObjectSpecs(
                       memberSpecs,

                       (serializer, argList) =>
            {
                var constructorSpecs = new MethodSpecs(FindConstructor(objType));
                constructorSpecs.Init();

                deserializeObj = MethodInvoker.InvokeMethod(serializer, constructorSpecs, null, argList);
                Debug.Assert(deserializeObj != null);
                return deserializeObj;
            },
                       (spec, value) =>
            {
                memberSpecs.TryGetMember(spec, out var memberInfo);
                memberInfo.SetValue(deserializeObj, value);
            },
                       (_, _) => deserializeObj,

                       (_, obj) => serializeObj = obj,
                       spec =>
            {
                memberSpecs.TryGetMember(spec, out var memberInfo);
                return memberInfo.GetValue(serializeObj);
            },
                       (_, _) => { }));
        }
예제 #3
0
 /// <summary>
 /// 调用函数
 /// </summary>
 /// <param name="serializer">命令行反序列器</param>
 /// <param name="methodSpecs">函数的参数说明</param>
 /// <param name="obj">调用函数时的this对象</param>
 /// <param name="argList">命令行参数,本集合会被修改,调用完毕后集合内是剩余的命令行参数</param>
 /// <returns>函数返回值</returns>
 public static object?InvokeMethod(
     CommandLineSerializer serializer,
     MethodSpecs methodSpecs,
     object?obj,
     LinkedList <string> argList)
 => InvokeMethod(serializer, methodSpecs, obj, argList, null);