Hello fellow programmers. Basically, I want to pass a dynamically built delegate to minimal api MapGet or MapPost method. This is the method that constructs the delegate:
private static Delegate GetDelegate(Type type, MethodInfo method, ParameterInfo[] parameters)
{
/* Method dynamically build this lambda expression:
* (Type1 arg1, Type2 arg2, ..., TypeN argN) =>
{
var instance = GetTypeInstance(type);
return instance.SomeMethod(arg1, arg2, ..., argN);
}
* Where N = number of arguments
*/
var paramExpresions = new List<ParameterExpression>();
foreach (var parameter in parameters)
paramExpresions.Add(Expression.Parameter(parameter.ParameterType, parameter.Name));
// Instance variable
var instance = Expression.Variable(type, "instance");
// Get instance of type
MethodInfo getTypeInstance = typeof(DynamicControllerCompiler).GetMethod("GetTypeInstance");
var callExpression = Expression.Call(getTypeInstance, Expression.Constant(type));
var expressionConversion = Expression.Convert(callExpression, type);
var assignSentence = Expression.Assign(instance, expressionConversion);
var returnTarget = Expression.Label(method.ReturnType);
var returnExpression = Expression.Return(returnTarget, Expression.Call(instance, method, paramExpresions), method.ReturnType);
var returnLabel = Expression.Label(returnTarget, Expression.Default(method.ReturnType));
var fullBlock = Expression.Block(
new[] { instance },
assignSentence,
returnExpression,
returnLabel
);
var lambda = Expression.Lambda(fullBlock, "testLambda", paramExpresions);
return lambda.Compile();
}
The referenced method "GetTypeInstance" just returns service from container, but for simplicity let it just be:
public static object GetTypeInstance(Type type)
{
return new EchoService();
}
The service is very simple:
public class EchoService
{
public string Echo(string message)
{
return message;
}
public string EchoDouble(string message)
{
return message + "_" + message;
}
}
So I want to map a get method to minimal api using it like this:
var type = typeof(EchoService);
foreach (var method in type.GetMethods())
{
ParameterInfo[] parameters = method.GetParameters();
var methodDelegate = GetDelegate(type, method, parameters);
//test
var result = methodDelegate.DynamicInvoke("test");
app.MapGet($"api/{method.Name}", methodDelegate);
}
To test if the dynamic delegate works, I call it with "DynamicInvoke" and everything seems fine. Yet if I pass the delegate to MapGet the error is thrown:
System.InvalidOperationException: 'A parameter does not have a name! Was it generated? All parameters must be named.'
I cannot seem to understand what is going on. The delegate works fine if called by DynamicInvoke, and inside all the parameters has names.