Alx*_*ndr 9 c# reflection algorithm
我正在用C#编写一个库,我稍后将其用于一个应用程序,我希望该库尽可能高效(即不要过于复杂化,以使其更高效).但是,我有一个关于如何最有效地使用类/方法的反射的问题,并说明了我已经简化了我的课程的问题:
class MyClass
{
private static Dictionary<string, object> methods;
public void Method1()
{
// Do something.
}
public void Method2()
{
// Do something else.
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我想要的是来自类(一个尚未创建的私有方法),取一个包含方法名的字符串,然后触发方法,就这么简单.最简单的方法是查看名称,获取具有该名称的方法并执行它,但这迫使我多次使用反射.这种私有方法可能被称为数千或数万次,并且需要快速.所以我想出了两个可能的解决方案.你可能会看到我添加了一个包含string-> object的静态字典(用实际类型替换对象,只写了对象,因为它适用于我的两个例子).然后我将添加一个静态构造函数,该构造函数通过类并将所有methodinfos添加到methods-dictionary中.然后问题是,在创建类的新实例时,我应该创建方法的绑定委托并将它们放在非静态私有字典中,或者我应该只使用方法字典中的MethodInfo来触发方法?
平均用例将创建此类的10个实例,并且对该方法进行1000次以上的调用,该方法应根据其字符串参数触发Method1或Method2(并且不,因为可扩展性,switch-case不是一个选项如上所述,这是一个简化的版本).实现这一目标的最有效方法是什么?
Eri*_*ert 12
显然没有人能够在没有实际尝试并进行性能测试的情况下回答这个问题,看看你的目标是否得到满足.
现代版本的框架中的反射比以前快得多,但它仍然没有简单地调用委托那么快.
我的建议是从你提出的解决方案开始:一次构建方法信息的缓存:
class MyClass
{
static Dictionary<string, MethodInfo> cache = new ...
public void InvokeByName(string name)
{
MethodInfo methodInfo = GetMethodInfoFromCache(name);
methodInfo.Invoke(this, new object[] {});
}
Run Code Online (Sandbox Code Playgroud)
当要求调用由特定实例上的字符串标识的方法作为接收器时,按名称查找方法info,然后使用给定的接收器调用它.衡量它的表现,看看它是否符合你的目标.如果确实如此,很棒; 不要浪费你宝贵的时间来尝试更快速地创造更快的东西.
如果这还不够快那么这就是我要做的事情:
class MyClass
{
static Dictionary<string, Action<MyClass>> cache = new ...
public void InvokeByName(string name)
{
GetActionFromCache(name).Invoke(this);
}
Run Code Online (Sandbox Code Playgroud)
那么GetActionFromCache有什么作用呢?如果缓存中已有操作,我们就完成了.如果没有,则通过Reflection获取MethodInfo.然后使用表达式树库来构建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();
Run Code Online (Sandbox Code Playgroud)
现在,您可以使用实例调用一个动作.把那东西粘在缓存中.
顺便提一下,这是一个非常简化的层面,C#4中的"动态"是如何工作的.我们的问题非常复杂,因为我们必须处理接收器和任何类型的参数.你比较容易.