【问题标题】:Store generic method + arg type + return type inside list to call it later将泛型方法 + arg 类型 + 返回类型存储在列表中以供稍后调用
【发布时间】:2020-07-10 20:36:35
【问题描述】:

我正在尝试使用不同的参数类型和返回类型来归档类似“特定事件的注册方法”之类的东西,到目前为止,我的计划是使用泛型实现的。

调用 RegisterMethod 函数后,我需要将给定的“方法”参数存储在列表中,包括其输入类型和输出类型。为了以后使用,我想用注册的类型调用给定的方法。

我现在遇到的问题如下:在服务器上调用 ProcessIncomingRequest 后,我​​需要将 byte[] 数据反序列化为我在 RegisterMethod 方法中定义的给定类型以及返回类型,以便响应客户端。但我不知道如何在代码中转换这些类型。

struct MethodData
{
    public string Name;
    public System.Reflection.MethodInfo MethodInfo;
    public Type ReturnType;
    public Type ArgumentType;
}

class NetworkServer
{
    List<MethodData> list = new List<MethodData>();
    public void RegisterMethod<In, Out>(string name, Func<NetworkClient, In, Out> method)
    {
        list.Add(new MethodData()
        {
            MethodInfo = method.Method,
            Name = name,
            ReturnType = typeof(Out),
            ArgumentType = typeof(In)
        });

        // Store the method including 
        // it the return type
        // In theory I want to add them to a List/Dictionary
        // and re-use the method + types in the
        // ProcessIncomingRequest method.
    }

    public void RegisterMethod<In>(string name, Action<NetworkClient, In> method)
    {
        list.Add(new MethodData()
        {
            MethodInfo = method.Method,
            Name = name,
            ArgumentType = typeof(In),
        });
        // Same as above, this method doesn't return anything. Its just a call and forget
    }

    public static void ProcessIncomingRequest(NetworkClient cl, string name, byte[] data)
    {
        var method = list.SingleOrDefault(x => x.Name.Equals(name));

        if(method != NULL)
        {
            var finalData = Serializer<Tin>(data);
            // Tin = it.ArgumentType
            // Tout = it.ReturnType
            // This is exactly what I would need to archive

            var retn = it.MethodInfo.Invoke(null, new[] { cl, finalData });
            if(retn != NULL && it.ReturnType != NULL)
                cl.Send<Tout>(retn);
        }

        // name represents the method name in the List
        // data represents represents the parameter values
        // The generic "Tin" and "Tout is the problem here
    }
}


static void main()
{
    NetworkServer server = new NetworkServer(9000);
    server.RegisterMethod<int, bool>("CheckValue", CheckValue);
    server.RegisterMethod<string>("Log", NotifyLogger);
    server.Start();
}


// Execute method with received data and return result to client
static bool CheckValue(NetworkClient cl, int value)
{
    return value >= 10;
}


// Execute data without the need of any return
static void NotifyLogger(NetworkClient cl, string logger)
{
    Console.WriteLine($"Incoming Logger request : {logger}");
    MyLogger.Write($"[SERVER] {logger}");
}

【问题讨论】:

    标签: c# types casting runtime


    【解决方案1】:

    如果你想call a method that takes a generic type parameter 使用类型对象,你需要使用反射。

    一些序列化库具有反序列化采用类型对象而不是泛型类型参数的方法,并序列化只采用“对象”的方法。如果有这样的方法,我会更喜欢这样的解决方案而不是反射魔法。

    【讨论】:

    • 谢谢,我不知道你能在运行时创建泛型方法。我想通了并解决了我的问题。我将第一个泛型参数类型、返回类型和方法信息本身存储在一个数组中。当 ProcessIncomingRequest 被调用时,我使用第一个 parm 类型为我的 Serializer 类创建一个通用方法并调用它。调用返回一个对象,但对象背后的数据仍然存在,我可以对其进行序列化,以便将其作为最终响应发送回客户端。
    猜你喜欢
    • 2014-10-16
    • 2016-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-24
    • 2011-05-11
    • 1970-01-01
    相关资源
    最近更新 更多