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
MakeGenericTypeshould get you going based on a way I interpret the question)...