我終於找到了解決我的問題!它涉及到一點點投射和反射,但實際上在我迄今爲止所做的所有測試中運行穩定。我按照以下步驟操作:
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#燈泡動作的所有用法。很難找到我的方式,但最終擊敗了挑戰。希望這有助於某個人,某處,某些時候!
所以這是一項調查? – TheGeekZn
我的團隊正致力於改進IDE工具(如代碼完成,靜態代碼分析等)。目前,我們想分析如何使用這些工具,以便找到可以改進的地方和方式。 –
這是一個基於發展問題而不是實踐的問答網站。我不認爲這個問題與SO有關。 – TheGeekZn