首页 新闻 会员 周边 捐助

表达式树反射

0
悬赏园豆:5 [已解决问题] 解决于 2014-09-30 16:53
            User u = new User();
            var method = u.GetType().GetMethod("Methods");

            var type1 = method.GetParameters()[0].ParameterType;
            var parameter1 = Expression.Parameter(type1, "pr1");

            var type2 = method.GetParameters()[1].ParameterType;
            var parameter2 = Expression.Parameter(type2, "pr2");

            var callExpression = Expression.Call(Expression.Constant(u), method, new Expression[] { parameter1, parameter2 });

            Expression<Action<string, int>> scall = Expression.Lambda<Action<string, int>>(callExpression, new ParameterExpression[] { parameter1, parameter2 });
            var executeMethods = scall.Compile();
            executeMethods("1", 1);

            u.Methods("ddd", 3);
    public class User
    {
        public void Methods(string name,int age)
        {
            Console.WriteLine(name+"-----"+age+s);
        }
    }

这几天学习看了资料 利用表达式树反射?

感觉这样写好麻烦啊?有帮忙优化一下的 或者改进的吗?

s_p的主页 s_p | 初学一级 | 园豆:140
提问于:2014-08-27 18:08
< >
分享
最佳答案
0

为什么要用表达式树?如果你有特别的需求,你可以用表达式树,对于你的这个代码,直接一个method.Invoke就解决了。

收获园豆:2
519740105 | 大侠五级 |园豆:5810 | 2014-08-27 18:37

嗯 你说的对

原因是 听说效率比传统的反射高。  

s_p | 园豆:140 (初学一级) | 2014-08-28 11:28

@s_p: 这个不一定就高哦,别“听说”。而且,即便真的高,又能高多少?相比你的这段代码的编写与执行,这个效率已经降低了很多了。

519740105 | 园豆:5810 (大侠五级) | 2014-08-28 11:32

@519740105: 我有测试 看到过 不是瞎扯的

s_p | 园豆:140 (初学一级) | 2014-08-28 11:33

@s_p: 我说的“别听说”的意思是这个效率影响不是非常的大,除非是实时系统。综合成本考虑,该用哪个。

另外,既然你要考虑到这个性能,那么,表达式的麻烦也就是你必须接受的。

519740105 | 园豆:5810 (大侠五级) | 2014-08-28 11:35

@s_p: 跟你探讨一个问题,你说使用expression调用实体方法比通过反射调用方法性能要高,但我做了个实验:

            var paramExp1 = Expression.Parameter(typeof(string), "a");

            var method = typeof(string).GetMethod("ToCharArray", new Type[0]);
            var callExpression = Expression.Call(paramExp1, method);

            var del = Expression.Lambda(callExpression, paramExp1).Compile();

            Stopwatch methodWatch = new Stopwatch();
            methodWatch.Start();
            for(int i = 0; i < 1000; i++)
            {
                method.Invoke("aaa", new object[0]);
            }
            methodWatch.Stop();
            Stopwatch expWatch = new Stopwatch();
            expWatch.Start();
            for (int i = 0; i < 1000; i++)
            {
                del.DynamicInvoke("aaa");
            }
            expWatch.Stop();
            var t1 = methodWatch.ElapsedTicks;
            var t2 = expWatch.ElapsedTicks;

行为很简单,就是把一个字符串转换为字符数组(调用String.ToCharArray()方法),但结果是:

t2远远大于t1(几次实验,t1都是1000-2000,而t2都是5000-7000)。

 

你能把你说的那个“看到过”的例子贴出来或发给我吗?

 

谢谢!

519740105 | 园豆:5810 (大侠五级) | 2014-09-05 10:56

@519740105: 

var paramExp1 = Expression.Parameter(typeof(string), "a");

            var method = typeof(string).GetMethod("ToCharArray", new Type[0]);
            var callExpression = Expression.Call(paramExp1, method);

            var del = Expression.Lambda<Func<string,char[]>>(callExpression, new ParameterExpression[] { paramExp1 }).Compile();;

            Stopwatch methodWatch = new Stopwatch();
            methodWatch.Start();
            for (int i = 0; i < 1000; i++)
            {
              method.Invoke("aaa", new object[0]);
            }
            methodWatch.Stop();

            Stopwatch expWatch = new Stopwatch();
            expWatch.Start();
            for (int i = 0; i < 1000; i++)
            {
                del("aaa");
            }
            expWatch.Stop();
            var t1 = methodWatch.ElapsedTicks;
            var t2 = expWatch.ElapsedTicks;
            Console.WriteLine(t1);
            Console.WriteLine(t2);

 

 

 我改成这样你看下

s_p | 园豆:140 (初学一级) | 2014-09-05 14:14

@s_p: 你的代码这笔了,只是以下代码:

var tmp = Expression.Lambda<Func<string,char[]>>(callExpression, new ParameterExpression[] { paramExp1 }).Compile();

的改变吗?我这里得到的结果还是很悬殊,还是t2大!

519740105 | 园豆:5810 (大侠五级) | 2014-09-05 14:42

@519740105: 你把我改的运行下 我这里是t2 小啊 我发图了 

s_p | 园豆:140 (初学一级) | 2014-09-05 14:46

@s_p: 恩搞明白了,是调用的时候,直接当作lambda表达式调用,而不是用动态调用。

519740105 | 园豆:5810 (大侠五级) | 2014-09-05 14:55

@519740105: 你把那个循环去掉你看时间 t2是0   O(∩_∩)O~

s_p | 园豆:140 (初学一级) | 2014-09-05 15:47

@s_p: 已经知道了,因为我还是用的DynamicInvoke,没注意你的代码del("aaa")。

519740105 | 园豆:5810 (大侠五级) | 2014-09-05 15:48

@519740105: 嗯 我也只是懂一些基本的 这个太复杂的看不懂 你有什么好的资料没!

s_p | 园豆:140 (初学一级) | 2014-09-05 16:06

@s_p: 木有,研究ing

519740105 | 园豆:5810 (大侠五级) | 2014-09-05 16:11
其他回答(3)
0

什么需求?对象能直接实例化出来,为什么要这样绕一大圈调用对象的成员方法呢

收获园豆:1
龙卷风摧毁停车场! | 园豆:210 (菜鸟二级) | 2014-08-27 18:19

原因是 听说效率比传统的高。 不知道合理不还有一个就是自己 喜欢多看看

支持(0) 反对(0) s_p | 园豆:140 (初学一级) | 2014-08-28 11:27
0

加油学。

收获园豆:1
forhells | 园豆:724 (小虾三级) | 2014-08-27 19:27

感觉学这个的少啊 有点难 朋友

支持(0) 反对(0) s_p | 园豆:140 (初学一级) | 2014-08-28 11:29
0

想要比传统反射效率高,var executeMethods = scall.Compile();你必须把编译得到的executeMethods的这个结果缓存,调用的时候直接调用缓存。

收获园豆:1
我叫So | 园豆:186 (初学一级) | 2014-08-31 22:27

支持(0) 反对(0) s_p | 园豆:140 (初学一级) | 2014-09-05 14:16
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册