Alex Aparin
Alex Aparin

Reputation: 4522

How to create type of func with specified generic types?

I want to create Func type with specified generic type arguments, something like that like, but only with one statement

Type create_type(Type[] types)
{
   return typeof(Func<>).MakeGenericType(types); // error if types.Length != 1
   return typeof(Func<,>).MakeGenericType(types); // error if types.Length != 2
   return typeof(Func<,,>).MakeGenericType(types); // error if types.Length != 3
   return typeof(Func<,,,>).MakeGenericType(types); // error if types.Length != 4
// .... 
}

Of course, I can create auxuliary array:

var func_types = new Type[] { typeof(Func<>), typeof(Func<,>) , //...}

But this solution seems too ugly for me

Note: array of types can be long (up to 15) and I want to find elegant solution. Unfortunately, I am creating such type from meta data, written in another language

Upvotes: 4

Views: 2126

Answers (2)

Jeroen Mostert
Jeroen Mostert

Reputation: 28809

Recall that generic types have names of the form T`N, where N is the number of generic parameters. So all Func delegates have a systematic name that allows us to easily get the type:

Type create_type(Type[] types) {
    return Type.GetType($"System.Func`{types.Length}").MakeGenericType(types);
}

No promises as to how efficient this is, but if you're constructing such types at runtime, that's probably not the primary concern anyway.


Given the existence of Expression.GetFuncType, this answer is of course inferior, but I'm leaving it up for educational purposes (of some sort). This stops working beyond 9 arguments, because System.Func delegates of more than 9 arguments live in System.Core, not mscorlib, and therefore require an assembly-qualified name. The fix is easy (throw in a check and conditionally add System.Core to the name), but unnecessary given the existence of GetFuncType.

Upvotes: 2

CSharpie
CSharpie

Reputation: 9477

There are static Methods in Expression class for Func and Action that do exaclty what you require

Expression.GetFuncType(Type[] types)

Expression.GetActionType(Type[] types)

Further Information here:

GetFuncType

GetActionType

Upvotes: 13

Related Questions