Function pointers in C#

前端 未结 2 1448
醉梦人生
醉梦人生 2020-12-24 16:07

I suppose in some ways either (or both) Delegate or MethodInfo qualify for this title. However, neither provide the syntactic niceness that I\'m lo

2条回答
  •  死守一世寂寞
    2020-12-24 16:25

    Here's another bit of code you could use; Reflection is rather slow, so if you expect your Dynamic function calls to be called frequently, you don't want method.Invoke inside the delegate:

    public delegate void DynamicAction(params object[] parameters);
    static class DynamicActionBuilder
    {
        public static void PerformAction0(Action a, object[] pars) { a(); }
        public static void PerformAction1(Action a, object[] p) {
            a((T1)p[0]);
        }
        public static void PerformAction2(Action a, object[] p) {
            a((T1)p[0], (T2)p[1]);
        }
        //etc...
    
        public static DynamicAction MakeAction(object target, MethodInfo mi) {
            Type[] typeArgs =
                mi.GetParameters().Select(pi => pi.ParameterType).ToArray();
            string perfActName = "PerformAction" + typeArgs.Length;
            MethodInfo performAction =
                typeof(DynamicActionBuilder).GetMethod(perfActName);
            if (typeArgs.Length != 0)
                performAction = performAction.MakeGenericMethod(typeArgs);
            Type actionType = performAction.GetParameters()[0].ParameterType;
            Delegate action = Delegate.CreateDelegate(actionType, target, mi);
            return (DynamicAction)Delegate.CreateDelegate(
                typeof(DynamicAction), action, performAction);
        }
    }
    

    And you could use it like this:

    static class TestDab
    {
        public static void PrintTwo(int a, int b) {
            Console.WriteLine("{0} {1}", a, b);
            Trace.WriteLine(string.Format("{0} {1}", a, b));//for immediate window.
        }
        public static void PrintHelloWorld() {
            Console.WriteLine("Hello World!");
            Trace.WriteLine("Hello World!");//for immediate window.
        }
    
        public static void TestIt() {
            var dynFunc = DynamicActionBuilder.MakeAction(null,
                typeof(TestDab).GetMethod("PrintTwo"));
            dynFunc(3, 4);
            var dynFunc2 = DynamicActionBuilder.MakeAction(null,
                typeof(TestDab).GetMethod("PrintHelloWorld"));
            dynFunc2("extraneous","params","allowed"); //you may want to check this.
        }
    }
    

    This will be quite a bit faster; each dynamic call will involve 1 typecheck per param, 2 delegate calls, and one array construction due to the params-style passing.

提交回复
热议问题