VSX是VS擴展,可以針對不同項目編寫插件,雖然接觸VSX的時間並不多,但是當了解VSX後深刻感受到VSX的魅力。
VSX的材料比較少,配置文件也很繁瑣,當初我也走了不少彎路。
這篇文章將幫助您更好的管理Package文件(繼承Package、注冊命令的那個文件),想要理解這篇文章您應當對VSX有基礎的了解,確保自己可以建立一個基礎的VSX菜單,如果目前您還不了解VSX也沒關系,我推薦您先閱讀明年我18的文章。
看過基礎材料後,感覺Package文件的內容真是多,包括初始化、注冊控件、菜單過濾、回調,就算把菜單過濾和回調挪走,一個典型的注冊命令代碼也有這麼多:
1 OleMenuCommand cmdidFindInSolutionExplorer = new OleMenuCommand(FindInSolutionExplorerCallback, 2 new CommandID(GuidList.guidConvenientCmdSet, (int)PkgCmdIDList.cmdidFindInSolutionExplorer)); 3 cmdidFindInSolutionExplorer.BeforeQueryStatus += new EventHandler(MenuFilter.ClinicalFilter); 4 mcs.AddCommand(cmdidFindInSolutionExplorer);
隨著插件功能的豐富,百十來個命令讓Package文件擁擠不堪,再加上過濾和回調,每次打開這個文件都頭皮發麻,(就算把回調和過濾分離成單獨文件,大批的回調和過濾函數也。。。)。
下面的解決方案可以讓你優雅的注冊命令,是讀codemaid源碼時學到的:
首先定義一個抽象類BaseCommand繼承OleMenuCommand,並在BaseCommand下定義兩個事件OnBeforeQueryStatus與OnExecute分別對應過濾和回調:
1 private static void BaseCommand_BeforeQueryStatus(object sender, EventArgs e) 2 { 3 BaseCommand command = sender as BaseCommand; 4 if (command != null) 5 { 6 command.OnBeforeQueryStatus(); 7 } 8 } 9 protected virtual void OnBeforeQueryStatus() 10 { 11 Enabled = true; 12 } 13 private static void BaseCommand_Execute(object sender, EventArgs e) 14 { 15 BaseCommand command = sender as BaseCommand; 16 if (command != null) 17 { 18 command.OnExecute(); 19 } 20 } 21 protected virtual void OnExecute() 22 { 23 }
在構造函數中注冊事件:
1 protected ClinicalVSXPackage Pkg { get; private set; } 2 3 protected BaseCommand(ClinicalVSXPackage pkg, CommandID id) 4 : base(BaseCommand_Execute, id) 5 { 6 Pkg = pkg; 7 BeforeQueryStatus += BaseCommand_BeforeQueryStatus; 8 }
Pkg是將Package類本身傳進來,方便傳遞dte等成員。
這樣就可以在Package文件中優雅的注冊命令了:
1 private readonly ICollection<BaseCommand> _commands = new List<BaseCommand>(); 2 3 private void RegisterCommands() 4 { 5 var mcs = MenuCommandService; 6 if (null == mcs) 7 return; 8 _commands.Add(new 命令1(this)); 9 _commands.Add(new 命令2(this)); 10 _commands.Add(new 命令3this)); 11 .... 12 foreach (var command in _commands) 13 mcs.AddCommand(command); 14 }
這樣當你打算新建一個命令,需要添加一個獨立的類繼承剛才的BaseCommand
並實現過濾和回調事件,一個典型的命令類:
1 internal class 命令1 : BaseCommand 2 { 3 public 命令1(Package pkg) 4 : base(pkg, new CommandID(CmdSetID, (int)PkgCmdIDList.命令ID)) 5 { } 6 7 protected override void OnBeforeQueryStatus() 8 { 9 } 10 protected override void OnExecute() 11 { 12 base.OnExecute(); 13 } 14 }