I am using C#/.NET 4.0 and a Protocol Buffers library (protobuf-net) which provides the following functionality.
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);
}
I need to wrap two of these calls with non-generic equivalents. Specifically, I want
void SerializeReflection(Stream destination, object instance);
object DeserializeReflection(Stream source, Type type);
that simply call the respective generic members of Serializer
at runtime. I have gotten the DeserializeReflection
method to work with the following code:
public static object DeserializeReflection(Stream stream, Type type)
{
return typeof(Serializer)
.GetMethod("Deserialize")
.MakeGenericMethod(type)
.Invoke(null, new object[] { stream });
}
The SerializeReflection
method is what is causing me trouble. I at first tried the following code:
public static void SerializeReflection(Stream stream, object instance)
{
typeof(Serializer)
.GetMethod("Serialize")
.MakeGenericMethod(instance.GetType())
.Invoke(null, new object[] { stream, instance });
}
The problem is that the part between typeof(Serializer)
and .Invoke(...)
is not working. The call to GetMethod("Serialize")
gets me an AmbiguousMatchException
, because there are four methods named "Serialize
."
I then tried using the overload of GetMethod
that takes an array of System.Type
to resolve the binding:
GetMethod("Serialize", new[] { typeof(Stream), instance.GetType() })
But this just made the result of GetMethod
null
.
How can I use reflection to get the MethodInfo
for void Serializer.Serialize<T>(Stream, T)
, where T
is instance.GetType()
?
The actual type arguments of a generic type are. reference types, wildcards, or. parameterized types (i.e. instantiations of other generic types).
From the point of view of reflection, the difference between a generic type and an ordinary type is that a generic type has associated with it a set of type parameters (if it is a generic type definition) or type arguments (if it is a constructed type). A generic method differs from an ordinary method in the same way.
Try to use next code snippet to see if it meets your need. It creates a close typed instance of method public static void Serialize<T>(Stream destination, T instance)
. In this case it select the first method with Stream
as parameter, but you can change this predicate method.GetParameters().Any(par => par.ParameterType == typeof(Stream))
to whatever you want
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 });
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With