创建动态功能

时间:2019-10-08 05:15:14

标签: c#

我已经在其目前正在尝试完成的功能完全的示例下重新创建了该类。使用.Net Framework 4.5创建控制台应用程序。在此过程中有很多帮助,我想为其他可能在本文中绊倒的人提供一个有效的例子。一旦一切就绪,我将在* 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(“我在做什么错,应该让代表更快吗?”)

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
  

非常感谢所有帮助我完成这项工作的人员。(向所有人致谢。)如果可以更有效地调用代表,我很想知道。

Adassko
Alexei Levenkov
Shingo
Tymtam

2 个答案:

答案 0 :(得分:1)

我不确定,但是你在追求这样的东西吗?

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

输出:

11
22

答案 1 :(得分:1)

选中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);
            ...
        }
    }
}