Create Delegate from MethodInfo with Output Parameters, without Dynamic Invoke
Asked Answered
E

1

2

I am trying to get a Delegate from a MethodInfo object that has Output Parameters. My code follows:

static void Main(string[] args) {

        MethodInfo m = typeof(Program).GetMethod("MyMethod2");

        IEnumerable<Type> paramsTypes = m.GetParameters().Select(p => p.ParameterType);

        Type methodType = Expression.GetDelegateType(paramsTypes.Append(m.ReturnType).ToArray());

        Delegate d = m.CreateDelegate(methodType);

        Action a = (Action)d;

        a();

    }

I'm getting is a System.InvalidCastException: Unable to cast object of type Delegate2$1 to type System.Action in the line that does "Action a = (Action)d". The thing is that I don't know what type to put in Action because I know that the correct type is not String, it is the Output equivalent of String (String&) in compilation.

MyMethod2 has an Output parameter, and I think that is where the problem is because when I test this with MyMethod which as an Input parameter, it works.

public static void MyMethod2(out String outputParameter) {

        outputParameter = "hey";

    }

public static void MyMethod(String inputParameter) {

  //does nothing 
    
}

Also, I know it is easier if I use Dynamic Invoke instead of a normal Delegate call but I'm not interested in that because I'm trying to enhance the performance of my program. Does anyone know how to do this? Thank you

Enure answered 22/6, 2020 at 13:20 Comment(0)
B
6

There is no Func or Action that can use out parameters. You can easily declare your own delegate type though:

public delegate void OutAction<T>(out T arg)

You could then use

OutAction<string> action = (OutAction) m.CreateDelegate(typeof(OutAction<string>));

You won't be able to use Expression.GetDelegateType because that only supports Func and Action, but you could write your own equivalent to work out the correct OutAction<> type to use based on the parameters, if you need to do it dynamically.

Barrybarrymore answered 22/6, 2020 at 13:24 Comment(7)
Thank you for the answer :) . When you I declare the type I should use 'public delegate void OutAction...' right?Enure
@fobisthename: Apologies, yes, that was a typo - fixed now.Barrybarrymore
Also, do you know if there is a way of using something like OutAction<> to create the Delegate without knowing beforehand the number of the arguments and also their types? I mean the signature of the resulting delegate.Enure
@fobisthename: I'm not sure what you mean. As I said in the answer, you could write something like Expression.GetDelegateType yourself that creates the delegate type with generics - but you wouldn't then be able to cast to anything like you do in your original code. Unfortunately we don't have the context of what you're trying to do, beyond what's in your question.Barrybarrymore
What I meant was that I do not know the type of the method that is called using the Delegate (or using Reflection), neither I know with which arguments that method is called. So all of this would have to be dealt with dynamically. Do you think that is possible? I can do it using Reflection with MethodInfo.Invoke, but I wanted to use Delegates for performance reasons.Enure
@fobisthename: So in your actual code you'd never be casting to a particular delegate type. If you have no idea about the methods (so it could have five parameters, three of which are out parameters for example) then you'd need to declare an enormous number of delegate types. I don't think that would work well. But if you could limit it to a certain set of signatures (still generic, and allowing maybe one out parameter per method, always the last one) then it could be done.Barrybarrymore
Yes that is exactly what I mean. I cannot limit neither the number of output parameters nor the number of input parameters. Thank you for the explanation :)Enure

© 2022 - 2024 — McMap. All rights reserved.