2011-05-25 21 views
0

是否有可能爲CLR創建從對象Y其中CLR中的派生類可以在保持intellisense的同時攔截/遮蓋父類的方法嗎?

  • 對象Y是Object類型的繼承對象X
  • 可用來反對X.對象X的
  • 呼叫者的Y所有方法認爲他們看到所有的Y的對象的方法上面
  • 對象X口罩和運行的每個方法做了一些「工作」前
  • 這「工作」可以包括計算的呼叫數量,或一些任意代碼
  • 對象X應該可以對任何對象的工作(這是確定的,如果它不反對密封對象的工作)

另一種實現可能會使用泛型其中Object T<Y>公開的所有方法,事件和包含對象的屬性Y

回答

1

是的。這被稱爲代理對象。 Castle DynamicProxy是專爲做到這一點。 Krzysztof Koźmic has produced an excellent tutorial about it

它通過在運行時創建一個對象(您的方案中的X)來工作,該對象從要代理的對象(對象Y)繼承。您提供了一個實現IInterceptor的對象,在調用某些方法時會調用它 - 您可以在代理生成選項類中指定這些對象。

唯一需要注意的是你希望截取的方法必須是虛擬的,但是你可以通過將對象包裝到另一個提供虛擬方法的代理中來解決這個問題(儘管我猜你可能想要代理對象因爲這樣做是真正的痛苦)。

0

看起來與您的需求相匹配的運行時代理的替代方案(在Y上調用方法時運行任意代碼)而不是您的問題(子類化策略)將使用編譯時解決方案(如PostSharpAfterthought)的AOP。這種方法允許您將代碼引入已編譯程序集中的現有方法,並且可以執行任何您想要的操作。

PostSharp通過允許定義描述如何修改類的屬性(方面)來工作。您可以將這些屬性放在方法,類型,程序集等中,當PostSharp作爲後構建步驟運行時,它將查找這些屬性並對編譯後的程序集執行轉換。

Afterthought的工作方式類似,使用屬性方案來確定適用於裝配中類型的修改。但是,Afterthought允許您在一個程序集中指定這些屬性/修正,並將它們應用到另一個程序集,以便實際上可以修改沒有任何屬性或對Afterthought的引用的目標程序集,也可能會修改您要引入的目標程序集。我在Afterthought中添加了這個特性,基於社區反饋,希望能夠在不建立對AOP工具(在這種情況下爲Afterthought)的依賴的情況下執行優雅的轉換,並且有可能在程序集的原始源代碼不再可用的情況下。

這是使用有感的例子對經修正的類型的每個方法調用的自動輸出執行時間:

public override void Amend(Method method) 
{ 
    method.Context<Stopwatch>() 

     .Before((T instance, string method, object[] parameters) 
      => { var s = new Stopwatch(); s.Start(); return s; }) 

     .After((T instance, string method, Stopwatch stopwatch, object[] parameters) 
      => Console.WriteLine(method + ": " + stopwatch.ElapsedMilliseconds); 
} 

在這種情況下在經修正的類型中的每個方法會在創建System.Diagnostics.Stopwatch實例每個方法的開始,並在每個方法的結尾寫出方法的名稱和執行時間。

相關問題