2013-09-23 58 views
-1

我可以通過在IActionManager [1]已知的每個UpdatableAction上安裝IActionHandler來觀察ReSharper操作的執行情況。不幸的是,燈泡操作(上下文操作和Quickfixes [2])不是ReSharper中的操作,因此操作管理器不知道。此外,似乎沒有類似的行動管理器的燈泡行動。觀察ReSharper燈泡操作的使用

  • 是否有一些(可能是通用的)獲取所有燈泡操作句柄?
  • 在這裏可以使用像ActionHandler這樣的東西來獲得有關燈泡行爲執行的信息嗎?

如果它的事項:我在ReSharper的8在Visual Studio提前2010

謝謝!

[1] http://confluence.jetbrains.com/display/NETCOM/2.03+Actions+and+Menu+Items+%28R8%29

[2] http://confluence.jetbrains.com/display/NETCOM/2.06+Quick-Fixes+and+Context+Actions+%28R8%29

+0

所以這是一項調查? – TheGeekZn

+0

我的團隊正致力於改進IDE工具(如代碼完成,靜態代碼分析等)。目前,我們想分析如何使用這些工具,以便找到可以改進的地方和方式。 –

+0

這是一個基於發展問題而不是實踐的問答網站。我不認爲這個問題與SO有關。 – TheGeekZn

回答

0

我終於找到了解決我的問題!它涉及到一點點投射和反射,但實際上在我迄今爲止所做的所有測試中運行穩定。我按照以下步驟操作:

R#具有IBulbItemsProvider接口,其實現動態加載並查詢燈泡項目,即每當打開一個R#菜單時,菜單項目都將包圍燈泡動作。我現在實現了以下提供程序:

[SolutionComponent] 
public class BulbItemInstrumentationComponent : IBulbActionprovider 
{ 
    public int Priority { get{ return int.MaxValue; } } 

    public object PreExecute(ITextControl tc) { return null; } 

    public void CollectActions(IntentionsBulbItems ibis, ...) 
    { 
    var bulbItems = ibis.AllBulbMenuItems; 
    foreach (var execItem in bulbItems.Select(item => item.ExecutableItem)) 
    { 
     var proxy = execItem as IntentionAction.MyExecutableProxi; 
     if (proxy != null) 
     { 
     proxy.WrapBulbAction(); 
     continue; 
     } 

     var exec = execItem as ExecutableItem; 
     if (exec != null) 
     { 
     exec.WrapBulbAction(); 
     continue; 
     } 

     throw new Exception("unexpected item type: " + execItem.GetType().FullName); 
    } 
    } 
} 

Priority的返回值確保我的提供程序被稱爲所有現有提供程序的最後一個。這會導致CollectAction()的參數IntensionsBulbItems已經包含從其他提供者收集的BulbMenuItems。

然後我遍歷所有這些項目,並安裝我的觀察包裝。因此,我需要將項目可執行文件下載到它們的實際類型。對於來自R#Core的燈泡項目,這兩種類型似乎是唯一使用的類型。來自R#Extensions的提供者實際上可能使用其他類型,在這種情況下,循環結尾處的Exception將被替換爲將來更加慷慨的處理;)

包裝本身在WrapBulbAction()擴展中實現方法。這些看起來像如下:

static class BulbItemInstrumentationExtensions 
{ 
    private static readonly MethodInfo MyExecutableProxiBulbActionSetter = 
    typeof (IntentionAction.MyExecutableProxi).GetProperty("BulbAction").GetSetMethod(true); 
    private static readonly FieldInfo ExecutableItemActionField = 
    typeof (ExecutableItem).GetField("myAction", BindingFlags.NonPublic | BindingFlags.Instance); 

    public static void WrapBulbAction(this IntentionAction.MyExecutableProxi proxi) 
    { 
    var originalBulbAction = proxy.BulbAction; 
    var bulbActionProxy = new LoggingBulbActionProxy(originalBulbAction); 
    MyExecutableProxiBulbActionSetter.Invoke(proxy, new object[] {bulbActionProxy}); 
    } 

    public static void WrapBulbAction(this ExecutableItem exec) 
    { 
    var originalAction = (Action) ExecutableItemActionField.GetValue(exec); 
    var actionProxy = new LoggingActionProxy(originalAction); 
    var newAction = (Action) (wrapper.Execute); 
    ExecutableItemActionField.SetValue(exec, newAction); 
    } 
} 

凡LoggingBulbActionProxy實施IBulbAction本身並委託給IBulbAction所有調用傳遞給它的構造,從而記錄所有調用執行()。 LoggingActionProxy是一個聲明Execute()方法的類,它需要記錄日誌,然後委託給傳遞給構造函數的Action。

現在我終於能夠記錄R#燈泡動作的所有用法。很難找到我的方式,但最終擊敗了挑戰。希望這有助於某個人,某處,某些時候!