我可以避免或优化此动态调用吗?

问题描述:

我想写一个类,它可以处理许多不同类型的输入,所有这些都实现相同的接口。我可以避免或优化此动态调用吗?

我有以下代码:

private IEnumerable<IPlan> DevisePlans(ITile tile, IEnumerable<ISpace> spaces) 
{ 
    MethodInfo method = GetType().GetMethod("DevisePlans", 
              BindingFlags.NonPublic | BindingFlags.Instance, 
              null, 
              new[] {tile.GetType(), typeof(ISpace)}, 
              null); 
    var type = typeof(Func<,,>).MakeGenericType(tile.GetType(), typeof(ISpace), typeof(IEnumerable<IPlan>)); 
    var planner = Delegate.CreateDelegate(type, this, method); 
    return spaces.SelectMany(s => (IEnumerable<IPlan>)planner.DynamicInvoke(tile, s)); 
} 

有很多DevisePlans各种实施方式的类中,每一个实现ITile的第一参数的类型。

private IEnumerable<IPlan> DevisePlans(Foo tile, ISpace space) { /* ... */ } 
private IEnumerable<IPlan> DevisePlans(Bar tile, ISpace space) { /* ... */ } 

这个工作,但我打电话DynamicInvoke为我的enumerable的每一个迭代。即使我不能完全避免动态调用,是否有任何方法来优化此方法,以便动态调用不再驻留在我的循环中?

+3

我能说清楚这是什么?有更多特定类型的'DevisePlans'重载的* lot *吗?要么...? – 2012-04-25 20:23:55

+1

你的代码目标有点模糊不清。你能给出一个高层次的概述吗?也许还有另一种方式*给皮肤上皮(可以这么说)。 – user7116 2012-04-25 20:23:58

就像你正在使用这个调用最具体的超载(未覆盖)所提供的tileDevisePlans看起来。假设我的理解是正确的(请不要告诉我,如果我错了),那么就使用dynamic - 它有一个内置的缓存并为此进行了优化:

return spaces.SelectMany(s => 
    (IEnumerable<IPlan>)DevisePlans((dynamic)tile, (dynamic)s) 
); 

和... 就是这样!然而,我会试图寻找一个包含多态性(针对ITile)或C#4.0方差的答案。

+0

这工作完美,非常清洁!我需要测试它的速度。我在哪里可以找到使用C#4.0差异的解决方案? – dlras2 2012-04-25 20:36:21

+0

@丹与问题更新/澄清我不认为差异方法的作品,对不起 – 2012-04-25 20:41:28

+0

为什么你使用'(动态)s'?我的代码编译没有它 - 只是为了让'ISpace'使用最具体的重载?另外,在'SelectMany'中指定类型参数可避免转换为'IEnumerable '。 – dlras2 2012-04-25 20:43:38

创建一个表达式树(从Expression.Call开始),编译它,并且您将拥有一个快速委托。您应该根据类型缓存委托,以便不会多次编译相同类型的代码。

+2

除非输入内容,否则不能这样做;如果它被键入,'Delegate.CreateDelegate'(在答案中)已经更直接和更快。 – 2012-04-25 20:24:57

+0

你可以编译一个ET,它接受一个对象参数并将其转换为正确的类型。铸造仍然比反思要好。 – fejesjoco 2012-04-25 20:27:16

想一下你在这里找的是visitor pattern。为每种类型定义一个ITileVisitor接口,并为它重载,然后ITile具有一个将访问者作为参数的访问方法。它的Visit的实现将导致调用正确的Devise超载。

+0

访问者模式要求我修改实现'ITile'的类,很遗憾我不能这样做。否则,像这样的事情是我会如何做到的。 – dlras2 2012-04-25 21:04:03