在C#中有效地使用反射
我正在C#中编写一个库,以后我将会使用一个应用程序,我希望这个库能够尽可能的高效(即不要过多地复杂一些事情,使它更有效率).但是,我有这个问题,关于如何最有效地使用反思在一个类/方法,并说明我已经简化了我的课程这个问题:
class MyClass { private static Dictionary<string,object> methods; public void Method1() { // Do something. } public void Method2() { // Do something else. } } 现在,我想要的是从类(一个私有方法尚未被创建),取一个包含method-name的字符串,然后点击该方法,简单的.这样做最简单的方法就是查看名称,获取一个名称的方法,然后执行它,但这迫使我多次使用反射.这种私有方法可能被称为数千或数万次,而且需要快速.所以我想出了两个可能的解决方案.你可能会看到我添加了一个包含string->对象的静态字典(用实际类型替换对象,只是写了对象,因为这两个我的例子).然后我会添加一个静态构造函数,通过该类,并将所有的methodinfos添加到方法字典中.然后提出一个问题,在创建一个类的新实例时,我应该为方法创建绑定的代理,并将它们放在非静态私有dict中,或者我应该简单地使用方法字典中的MethodInfo来激发方法? 平均用例将创建10个此类的实例,并且有1000个调用方法,该方法应该触发方法1或方法2,具体取决于它的字符串参数(而不是,switch-case不是一个选项,因为可扩展性如上所述,这是一个简化版本).实现这一目标最有效的方法是什么? 解决方法
显然没有人可以在没有实际尝试的情况下回答这个问题,并进行性能测试,看看你的目标是否得到满足.
反思在现代版本的框架中比以前更快,但它仍然不如简单地调用代理那么快. 我的建议是从您提出的解决方案开始:构建方法信息的缓存一次: class MyClass { static Dictionary<string,MethodInfo> cache = new ... public void InvokeByName(string name) { MethodInfo methodInfo = GetMethodInfoFromCache(name); methodInfo.Invoke(this,new object[] {}); } 当被要求调用由特定实例上的字符串标识的方法作为接收方时,按名称查找方法信息,然后使用给定的接收方调用它.衡量其性能,看看它是否符合您的目标.如果它是,伟大的不要浪费任何更多的宝贵时间,试图使更快的速度已经够快了. 如果这还不够快,那么我会做什么: class MyClass { static Dictionary<string,Action<MyClass>> cache = new ... public void InvokeByName(string name) { GetActionFromCache(name).Invoke(this); } 那么GetActionFromCache做什么呢?如果缓存中已经有一个动作,我们就完成了.如果没有,则通过Reflection获取MethodInfo.然后使用Expression Tree库构建一个Lambda: var methodInfo = SomehowGetTheMethodInfo(name); // We're going to build the lambda (MyType p)=>p.<named method here>() var p = Expression.Parameter(typeof(MyType),"p")); var call = Expression.Call(p,methodInfo); var lambda = Expression.Lambda<Action<MyType>>(call,p); var action = lambda.Compile(); 现在你有一个可以用实例调用的动作.把东西放在缓存中. 顺便提一句,这是一个令人难以置信的简化的水平,C#4中的“动态”是如何工作的.我们的问题是非常复杂的,因为我们必须处理接收者和任何类型的参数.你比较容易. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- Oracle的ORA_HASH是“随机的”吗?
- ruby – Capistrano 3 – 错误:抱歉,你必须有一个tty才能运
- ruby-on-rails – Rails用户注册邮件确认
- objective-c – 如何为一个重复的目标创建一个prefix.pch文
- EF 配置Oracle数据库 EntityType“PersonInfoTest”未定义键
- 解析XML文件的具体案例
- c# – 我应该如何使用DataflowBlockOptions.CancellationTo
- W/ResourceType( 4896): Bad XML block: header size 215 o
- 如何在VC中调试未初始化的变量
- ruby-on-rails-3 – 使用delayed_job的重复计划