Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a generic type for Tuples

I've clearly established how to make a generic Tuple as follows when the number of items is known in advance...

        Type t = typeof(Tuple<,,>);
        Type[] keys = new Type[] { typeof(string), typeof(string), typeof(int) };
        Type specific = t.MakeGenericType(keys);

but what if the number of objects in the "keys" array is variable? How to you start the ball rolling with the initial assignment to "t"?

Cheers. Craig

like image 636
Craig D Avatar asked Jun 13 '11 14:06

Craig D


2 Answers

Personally, I would have an array of the generic type definitions:

Type[] tupleTypes = {
    typeof(Tuple<>),
    typeof(Tuple<,>),
    typeof(Tuple<,,>),
    typeof(Tuple<,,,>),
    typeof(Tuple<,,,,>),
    typeof(Tuple<,,,,,>),
    typeof(Tuple<,,,,,,>),
    typeof(Tuple<,,,,,,,>),
};

You could do this in code, but it would be a bit of a pain... probably something like:

Type[] tupleTypes = Enumerable.Range(1, 8)
                              .Select(x => Type.GetType("System.Tuple`" + x)
                              .ToArray();

Or avoiding the array:

Type generic = Type.GetType("System.Tuple`" + keys.Length);
Type specific = generic.MakeGenericType(keys);
like image 187
Jon Skeet Avatar answered Oct 03 '22 17:10

Jon Skeet


Yet another way of building tupleTypes through Tuple.Create:

// once
Type[] tupleTypes = typeof(Tuple).GetMethods(BindingFlags.Public | BindingFlags.Static)
    .Where(mi => mi.IsGenericMethod && mi.Name == "Create")
    .Select(mi => mi.ReturnType.GetGenericTypeDefinition())
    .Distinct() // make sure there is no duplicated return types
    .OrderBy(t => t.GetGenericArguments().Length)
    .ToArray(); // expect start from Tuple<>

// instant type creation
Type tupleType = tupleTypes[types.Length-1].MakeGenericType(types);

Of course that expects that class System.Tuple will contain static Create methods that only produces Tuple<...>.

like image 28
ony Avatar answered Oct 03 '22 17:10

ony