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

与世无争的帅哥 提交于 2019-12-11 14:47:44

问题


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");
    }
}

回答1:


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.




回答2:


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);


来源:https://stackoverflow.com/questions/26670421/c-sharp-create-delegate-of-method-where-parameter-types-are-unknown-in-runtime

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!