Newtonsoft 序列化后 C# InvokeMethod 失败

C# InvokeMethod fail after Newtonsoft serialize

我正在使用 Type.InvokeMember 方法调用在 C# 中动态调用一个方法。
我有 2 种方法,一种接受字符串参数,另一种接受 int 参数。
该代码在代码中初始化时工作正常,但在 Newtonsoft.Json 序列化后失败。
调试没有帮助,因为类型似乎是正确的。完整代码如下:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;

namespace DynamicMethodCall
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Command> commands = new List<Command>()
            {
                new Command() { ClassName="Module1", MethodName="Method1", Parameters= new object[] { "1" } },
                new Command() { ClassName="Module1", MethodName="Method2", Parameters= new object[] { 1 } }
            };

            foreach (var command in commands)
            {
                string result = command.Invoke();
                Console.WriteLine(result);
            }

            File.WriteAllText("commands.json", JsonConvert.SerializeObject(commands));
            commands = JsonConvert.DeserializeObject<List<Command>>(File.ReadAllText("commands.json"));

            foreach (var command in commands)
            {
                string result = command.Invoke();
                Console.WriteLine(result);
            }
            Console.ReadLine();
        }
    }

    public class Command
    {
        public string ClassName { get; set; }
        public string MethodName { get; set; }
        public object[] Parameters { get; set; }

        public string Invoke()
        {
            try
            {
                Type type = Type.GetType("DynamicMethodCall." + ClassName);
                object instance = Activator.CreateInstance(type);
                string response = (string)type.InvokeMember(MethodName,
                    BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance,
                    null, instance, Parameters);
                return response;
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }
    }

    public class Module1
    {
        public string Method1(string x)
        {
            return $"You called Method1 in Module1 with arg {x}.";
        }

        public string Method2(int x)
        {
            return $"You called Method2 in Module1 with arg {x}.";
        }
    }
}


它returns

意思是在Newtonsoft序列化-反序列化之后,带有int参数的方法不起作用。 有人知道问题出在哪里吗?

您期望 JSON 数值将被反序列化为 int - 因为这就是它的开头。实际上,它被反序列化为 long。我相信这就是“Json.NET 对没有小数点的数字所做的”。 (我看不到更改它的选项,而且我不确定是否有一个选项有意义。)

你可以通过在反序列化前后添加这一行来观察:

Console.WriteLine(commands[1].Parameters[0].GetType());

您说:“调试无济于事,因为类型似乎是正确的。” - 但在这种情况下,它们 正确,因为您最终会尝试使用 long 值调用该方法。

从根本上说,您序列化的信息比原来少 - 因为您没有序列化类型信息。虽然 Json.NET 确实有一个 TypeNameHandling 设置在某些情况下可以帮助解决这个问题,但我还没有设法说服它简单地传播实际类型(以便它可以反序列化)。

或者,您可以 use a custom converter to deserialize to int instead。但是,当然,如果您以 long 开头,那也是不正确的...