2

我正在尝试编写一个可以处理许多不同类型的输入的类,所有这些都实现相同的接口。

我有以下代码:

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我的可枚举的每一次迭代。即使我不能完全避免动态调用,有没有办法优化这个方法,使动态调用不再驻留在我的循环中?

4

3 回答 3

5

看起来您正在使用它来调用所提供的最具体的重载(而不是覆盖)。假设我的理解是正确的(如果我错了,请告诉我),然后使用- 它有一个内置缓存并为此进行了优化:DevisePlanstiledynamic

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

而且……就是这样

但是,我很想寻找涉及多态性(反对ITile)或 C# 4.0 方差的答案。

于 2012-04-25T20:28:16.407 回答
0

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

于 2012-04-25T20:24:13.993 回答
0

想想你在这里寻找的是访问者模式。为每种类型定义一个带有重载的 ITileVisitor 接口,然后 ITile 有一个以访问者为参数的 Visit 方法。它的访问实现将导致正确的设计重载被调用。

于 2012-04-25T20:59:31.923 回答