0

I have recreated the class below its a fully functional example of what I am currently trying to accomplish. Create a Console Application using .Net Framework 4.5. There has been much help along the way and I wanted to make a working example for others that might stumble along this post. Once everything is in order I will mark the top of the solution with *FIXED.

//*FIXED AND WORKING added benchmark for each variation available only issue is the delegates are slower then MethodInfo.Invoke
using System;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace MethodInfoToDelgateInvocation
{
    class Program
    {
        static FindMethods findMethods = new FindMethods();
        static DelegateRef delegateRef = new DelegateRef();
        static Test test = new Test();
        static Stopwatch sw = new Stopwatch();

        static void Main(string[] args)
        {
            findMethods.FindNow(new Test());
            sw.Start();
            for (int i = 0; i < 10000000; i++)
            {
                test.HelloWorld(35, "Too Cool", 5.11F);
            }
            sw.Stop();
            Console.WriteLine($"Direct Invoke Time {sw.Elapsed}");
            sw.Reset();
            sw.Start();
            for (int i = 0; i < 10000000; i++)
            {
                //Test to see if delegateRef will fire off the TestMethod
                delegateRef.DelegateReference.Method.Invoke(delegateRef.Class, new object[3] { 35, "Too Cool", 5.11F });
            }
            sw.Stop();
            Console.WriteLine($"Delegate.Method.Invoke Time {sw.Elapsed}");
            sw.Reset();
            sw.Start();
            for (int i = 0; i < 10000000; i++)
            {
                delegateRef.DelegateReference.DynamicInvoke(new object[3] { 35, "Too Cool", 5.11F });
            }
            sw.Stop();
            Console.WriteLine($"Delegate.DynamicInvoke Time {sw.Elapsed}");
            sw.Reset();
            sw.Start();            
            for (int i = 0; i < 10000000; i++)
            {
                delegateRef.Method.Invoke(delegateRef.Class, new object[3] { 35, "Too Cool", 5.11F });
            }
            sw.Stop();
            Console.WriteLine($"MethodInfo.Invoke Time {sw.Elapsed}");
            sw.Reset();
            ConsoleKeyInfo key;
            do
            {
                key = Console.ReadKey();
            } while (key.Key != ConsoleKey.Escape);
        }
        [AttributeUsage(AttributeTargets.Field | AttributeTargets.Method)]
        public class RSync : Attribute
        {
        }
        public class DelegateRef
        {
            public int ClassId;
            public int Index;
            public Delegate DelegateReference;
            public MethodInfo Method;
            public object Class;
        }
        public class Test
        {
            [RSync]
            public void HelloWorld(int age, string name, float height)
            {
                //Console.WriteLine($"Age {age} Name {name} Height {height}");
            }
        }
        public class FindMethods
        {
            public void FindNow(Test test)
            {
                const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance
                | BindingFlags.DeclaredOnly | BindingFlags.SetProperty | BindingFlags.GetProperty;
                var methods = test.GetType().GetMethods().Where(methodInfo => methodInfo.GetCustomAttributes(typeof(RSync), true).Length > 0).ToList();
                var fields = test.GetType().GetFields(flags).Where(fieldInfo => fieldInfo.GetCustomAttributes(typeof(RSync), true).Length > 0).ToList();
                if (methods.Count == 0 && fields.Count == 0) return;

                foreach (var methodInfo in methods)
                {
                    //shingo's ideology mixed with Adassko expression tree idea
                    var actionType = Expression.GetActionType(methodInfo.GetParameters().Select(p => p.ParameterType).ToArray());
                    Console.WriteLine($"Action type {actionType}");
                    Console.WriteLine($"MethodInfo {methodInfo}");
                    delegateRef.DelegateReference = Delegate.CreateDelegate(actionType, null, methodInfo);
                    delegateRef.Method = methodInfo;
                    delegateRef.Class = test;
                }
            }
        }
    }
}

BenchMark ("What am I doing wrong shouldnt the delegate be faster?")

Direct Invoke Time 00:00:00.0405356
Delegate.Method.Invoke Time 00:00:04.3252286
Delegate.DynamicInvoke Time 00:00:17.3568062
MethodInfo.Invoke Time 00:00:03.9669439

Big thank you to all those that had helped me get this working.. (Upvote's to everyone.) If the Delegate can be invoked more efficiently I would love to know.

Adassko
Alexei Levenkov
Shingo
Tymtam
3

2 Answers 2

1

I'm not sure, but are you after something like this?

var fs = new List<Func<string, int>>();

int f1(string s) { return s.Length; };
int f2(string s) { return s.Length * 2; };

fs.Add(f1);
fs.Add(f2);

foreach(var f in fs )
{
    Console.WriteLine(f("Is this it?"));
}

Output:

11
22
Sign up to request clarification or add additional context in comments.

Comments

1

Check Type.MakeGenericType

public static Type GetDelegateType(Type[] paramTypes, bool noReturnType)
{
    if(noReturnType) //Action
    {
        switch (paramTypes.Length)
        {
            case 0: return typeof(Action);
            case 1: return typeof(Action<>).MakeGenericType(paramTypes);
            case 2: return typeof(Action<,>).MakeGenericType(paramTypes);
            ...
        }
    }
    else //Func
    {
        switch (paramTypes.Length)
        {
            case 1: return typeof(Func<>).MakeGenericType(paramTypes);
            case 2: return typeof(Func<,>).MakeGenericType(paramTypes);
            ...
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.