使用System.Type调用泛型方法

Tim*_*lds 5 .net c# generics system.reflection

我使用的是C#/ .NET 4.0和一个Protocol Buffers库(protobuf-net),它提供了以下功能.

public static class Serializer {
    public static void Serialize<T>(Stream destination, T instance);
    public static void Serialize<T>(SerializationInfo info, T instance);
    public static void Serialize<T>(XmlWriter writer, T instance);
    public static void Serialize<T>(SerializationInfo info, StreamingContext context, T instance);
    public static T Deserialize<T>(Stream source);
}
Run Code Online (Sandbox Code Playgroud)

我需要使用非泛型等价物包装其中两个调用.具体来说,我想要

void SerializeReflection(Stream destination, object instance);
object DeserializeReflection(Stream source, Type type);
Run Code Online (Sandbox Code Playgroud)

它只是Serializer在运行时调用相应的通用成员.我已经得到了DeserializeReflection使用以下代码的方法:

public static object DeserializeReflection(Stream stream, Type type)
{
    return typeof(Serializer)
        .GetMethod("Deserialize")
        .MakeGenericMethod(type)
        .Invoke(null, new object[] { stream });
}
Run Code Online (Sandbox Code Playgroud)

这种SerializeReflection方法给我带来了麻烦.我刚开始尝试以下代码:

public static void SerializeReflection(Stream stream, object instance)
{
    typeof(Serializer)
        .GetMethod("Serialize")
        .MakeGenericMethod(instance.GetType())
        .Invoke(null, new object[] { stream, instance });
}
Run Code Online (Sandbox Code Playgroud)

问题是,之间的部分typeof(Serializer).Invoke(...)不工作.调用GetMethod("Serialize")让我一个AmbiguousMatchException,因为有四个方法名为" Serialize."

然后我尝试使用重载GetMethod来获取System.Type解决绑定的数组:

GetMethod("Serialize", new[] { typeof(Stream), instance.GetType() })
Run Code Online (Sandbox Code Playgroud)

但这只是结果GetMethod null.

如何使用反射来获取MethodInfovoid Serializer.Serialize<T>(Stream, T),在那里Tinstance.GetType()

Ily*_*nov 4

尝试使用下一个代码片段看看它是否满足您的需求。它创建 method 的封闭类型实例public static void Serialize<T>(Stream destination, T instance)。在本例中,它选择第一个方法作为Stream参数,但您可以将此谓词更改method.GetParameters().Any(par => par.ParameterType == typeof(Stream))为您想要的任何内容

public static object DeserializeReflection(Stream stream, object instance)
{
   return typeof(Serializer)
        .GetMethods()
        .First(method => method.Name == "Serialize" && method.GetParameters().Any(par => par.ParameterType == typeof(Stream)))
        .MakeGenericMethod(instance.GetType())
        .Invoke(null, new object[] { stream, instance });
}
Run Code Online (Sandbox Code Playgroud)