2012-04-25 89 views
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爲我的enumerable的每一個迭代。即使我不能完全避免動態調用,是否有任何方法來優化此方法,以便動態調用不再駐留在我的循環中?

+3

我能說清楚這是什麼?有更多特定類型的'DevisePlans'重載的* lot *嗎?要麼...? – 2012-04-25 20:23:55

+1

你的代碼目標有點模糊不清。你能給出一個高層次的概述嗎?也許還有另一種方式*給皮膚上皮(可以這麼說)。 – user7116 2012-04-25 20:23:58

回答

5

就像你正在使用這個調用最具體的超載(未覆蓋)所提供的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

0

創建一個表達式樹(從Expression.Call開始),編譯它,並且您將擁有一個快速委託。您應該根據類型緩存委託,以便不會多次編譯相同類型的代碼。

+2

除非輸入內容,否則不能這樣做;如果它被鍵入,'Delegate.CreateDelegate'(在答案中)已經更直接和更快。 – 2012-04-25 20:24:57

+0

你可以編譯一個ET,它接受一個對象參數並將其轉換爲正確的類型。鑄造仍然比反思要好。 – fejesjoco 2012-04-25 20:27:16

0

想一下你在這裏找的是visitor pattern。爲每種類型定義一個ITileVisitor接口,併爲它重載,然後ITile具有一個將訪問者作爲參數的訪問方法。它的Visit的實現將導致調用正確的Devise超載。

+0

訪問者模式要求我修改實現'ITile'的類,很遺憾我不能這樣做。否則,像這樣的事情是我會如何做到的。 – dlras2 2012-04-25 21:04:03