简体   繁体   中英

C# Create delegate of method where parameter types are unknown in runtime

What I am trying to do is the following (which I necessarily don't know if it's even possible); I know a run time type. I know which method I want to invoke in run time. However, I don't know this in compile time.

The GetFunction method won't be able to create a delegate of the given methodInfo since the inparam isn't of type object.

Is there a way to create a delegate of a function where I only know a Type and a MethodInfo of the method I wish to delegate?

public sealed class Functions {
    public static int SetStrValue(string s) {
        // set a string
    }

    public static int SetIntValue(int i) {
        // set an int
    }
}

public sealed class GetFunctions {
    public Func<object, int> GetFunction(Type type, MethodInfo methodInfo) {
        // what I would like to do.
        Func<object, int> func = Delegate.CreateDelegate(typeof(Func<object, int>), methodInfo);
        return t => func(t);
    }
}

public class InvokeFunctions {
    public void invokeFunction() {
        Type t = typeof(String);
        MethodInfo methodInfo = typeof(Functions).GetMethod("SetStrValue");
        int i = GetFunctions.GetFunction(t, methodInfo).Invoke("hello");
    }
}

You can use expression trees to create a delegate. As the compile time type is not known you could try to cast the parameter to the appropriate type at runtime.

public sealed class GetFunctions
{
    public static Func<object, int> GetFunction(MethodInfo methodInfo)
    {
        var obj = Expression.Parameter(typeof (object), "obj");
        var convert = Expression.Convert(obj, methodInfo.GetParameters().First().ParameterType);
        var call = Expression.Call(methodInfo, convert);
        var lambda = Expression.Lambda<Func<object, int>>(call, obj);

        return lambda.Compile();
    }
}

public class InvokeFunctions
{
    public void invokeFunction()
    {
        MethodInfo methodInfo = typeof(Functions).GetMethod("SetStrValue");
        int i = GetFunctions.GetFunction(methodInfo).Invoke("hello");

        MethodInfo methodInfo2 = typeof(Functions).GetMethod("SetIntValue");
        int i2 = GetFunctions.GetFunction(methodInfo2).Invoke(1);
    }
}

I've removed the Type parameter and taken it directly from Method's first parameter, If that's not the intended behavior you can change it.

You can use generics to simplify this to just:

public sealed class Functions 
{
    public static int SetValue<T>(T input) 
    {
        // set a value of type T
    }
}

And call the function with:

Functions.SetValue<string>("hello");

Or you could use a generic delegate definition if you still want to use delegates:

public delegate int MyDelegateFunction<T>(T input);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM