I have a string serialization utility that takes a variable of (almost) any type and converts it into a string. Thus, for example, according to my convention, an integer value of 123 would be serialized as "i:3:123" (i=integer; 3=length of string; 123=value).
The utility handles all primitive type, as well as some non-generic collections, like ArrayLists and Hashtables. The interface is of the form
public static string StringSerialize(object o) {}
and internally I detect what type the object is and serialize it accordingly.
Now I want to upgrade my utility to handle generic collections. The funny thing is, I can't find an appropriate function to detect that the object is a generic collection, and what types it contains - both of which pieces of information I need in order to serialize it correctly. To date I've been using coding of the form
if (o is int) {// do something}
but that doesn't seem to work with generics.
What do you recommend?
EDIT: Thanks to Lucero, I've gotten closer to the answer, but I'm stuck at this little syntactical conundrum here:
if (t.IsGenericType) {
if (typeof(List<>) == t.GetGenericTypeDefinition()) {
Type lt = t.GetGenericArguments()[0];
List<lt> x = (List<lt>)o;
stringifyList(x);
}
}
This code doesn't compile, because "lt
" is not allowed as the <T>
argument of a List<>
object. Why not? And what is the correct syntax?
Re your conundrum; I'm assuming stringifyList
is a generic method? You would need to invoke it with reflection:
MethodInfo method = typeof(SomeType).GetMethod("stringifyList")
.MakeGenericMethod(lt).Invoke({target}, new object[] {o});
where {target}
is null
for a static method, or this
for an instance method on the current instance.
Further - I wouldn't assume that all collections are a: based on List<T>
, b: generic types. The important thing is: do they implement IList<T>
for some T
?
Here's a complete example:
using System;
using System.Collections.Generic;
static class Program {
static Type GetListType(Type type) {
foreach (Type intType in type.GetInterfaces()) {
if (intType.IsGenericType
&& intType.GetGenericTypeDefinition() == typeof(IList<>)) {
return intType.GetGenericArguments()[0];
}
}
return null;
}
static void Main() {
object o = new List<int> { 1, 2, 3, 4, 5 };
Type t = o.GetType();
Type lt = GetListType(t);
if (lt != null) {
typeof(Program).GetMethod("StringifyList")
.MakeGenericMethod(lt).Invoke(null,
new object[] { o });
}
}
public static void StringifyList<T>(IList<T> list) {
Console.WriteLine("Working with " + typeof(T).Name);
}
}