4

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

0

2 Answers 2

13

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

Sign up to request clarification or add additional context in comments.

5 Comments

that's brilliant answer!
Then I retract all my comments above about ugly code being needed :) Turns out it's just a question of who's going to have to write that ugly or convoluted code - referencesource.microsoft.com/#System.Core/Microsoft/Scripting/…
@CSharpie, Is there some analogue of such method for tuple type?
@АлександрЛысенко It appears not, but i also dont see the point why would someone create a Tuple-Type via reflection. Tuples are designed to be used in a small (local) scope. so they should never leave the body of a method. Anything else tends to be a codesmell in the firstplace.
@Lasse V. Karlsen, I thought that implementation will intrigue you)) referencesource.microsoft.com/System.Core/…
2

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.