• visual studio 插件开发(3) 优雅绑定菜单命令


    在前面两篇文章中,我们知道如果要将菜单和命令绑定起来可以通过以下的代码来完成。
    public sealed class SimpleCommandPackage : Package
    { 
      protected override void Initialize()
      {
        base.Initialize();
    
        OleMenuCommandService mcs = GetService(typeof(IMenuCommandService))
          as OleMenuCommandService;
        if ( null != mcs )
        {
          CommandID menuCommandID = new CommandID(GuidList.guidSimpleCommandCmdSet,
            (int)PkgCmdIDList.cmdidMyFirstCommand);
           MenuCommand menuItem = new MenuCommand(MenuItemCallback, menuCommandID );               
           mcs.AddCommand( menuItem );
        }
      }
      private void MenuItemCallback(object sender, EventArgs e)
      {
      }
    }
    

      

    上面的代码虽然现在看起来没有什么问题,不过可以想象当我们的命令越来越多的时候。initialize方法中的绑定事件会越来越多,而且最重要的是这些绑定的代码看起来都差不多。所以我们是不是可以使得这些绑定的代码更加简单和优雅呢?
     
    使用命令模式
     
    命令设计模式的介绍可以看这里,通过命令模式我们最终实现的效果应该是这样声明一个菜单:
     
    然后在Initialize中一句话搞定。这样做的好处就是一个命令就是一个类,清晰明了。而且每个命令的事件都聚合在这个类中了。
     
    注意到上图中两个红线标出的对象。CommandID特性将此命令与vsct中的命令联系起来(通过guid和id),而MenuCommand类则定义了一些公共的事件和方法。
    MenuCommand类:
      #region - 变量 -
     
            private readonly Package package;
            private readonly CommandID commandId;
            private OleMenuCommand oleMenuCommand;
     
            #endregion
     
            #region - 属性 -
     
            public CommandID CommandId
            {
                get { return commandId; }
            }
     
            protected Package Package
            {
                get { return package; }
            }
     
            protected IServiceProvider ServiceProvider
            {
                get { return package; }
            }
     
            protected OleMenuCommand OleMenuCommand
            {
                get { return oleMenuCommand; }
            }
     
            #endregion
     
            #region - 构造函数 -
     
            protected internal MenuCommand(Package package)
            {
                this.package = package;
                foreach (object attr in GetType().GetCustomAttributes(false))
                {
                    CommandIDAttribute idAttr = attr as CommandIDAttribute;
                    if (idAttr != null)
                    {
                        commandId = new CommandID(idAttr.Guid, (int)idAttr.Command);
                    }
                }
            }
     
            #endregion
     
            #region - 需要被重写的方法 -
     
            protected virtual void OnExecute(OleMenuCommand command)
            {
            }
     
            protected virtual void OnQueryStatus(OleMenuCommand command)
            {
            }
     
            protected virtual void OnChange(OleMenuCommand command)
            {
            }
     
            #endregion
     
            #region - 方法 -
     
            public void Bind()
            {
                if (package == null)
                {
                    return;
                }
     
                OleMenuCommandService mcs = ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
                if (mcs == null)
                {
                    return;
                }
     
                oleMenuCommand = new OleMenuCommand(
                  ExecuteMenuCommandCallback,
                  ChangeCallback,
                  BeforeStatusQueryCallback,
                  commandId);
                mcs.AddCommand(oleMenuCommand);
            }
     
            private void ExecuteMenuCommandCallback(object sender, EventArgs e)
            {
                OleMenuCommand command = sender as OleMenuCommand;
                if (command != null) OnExecute(command);
            }
     
            private void ChangeCallback(object sender, EventArgs e)
            {
                OleMenuCommand command = sender as OleMenuCommand;
                if (command != null) OnChange(command);
            }
     
            private void BeforeStatusQueryCallback(object sender, EventArgs e)
            {
                OleMenuCommand command = sender as OleMenuCommand;
                if (command != null) OnQueryStatus(command);
            }
     
            #endregion
    

      

    在MenuCommand的构造函数中,通过GetCustomAttributes方法得到类上面的CommandID,然后在bind方法中将得到的GUID和ID绑定到OleMenuCommand方法上。OleMenuCommand在新建的时候有三个事件也一同使用虚函数实现出来,以便继承类重写自己的操作。
     
  • 相关阅读:
    设计模式-Note9-行为变化类
    设计模式-Note8-数据结构类
    设计模式-Note7-状态变化类
    设计模式-Note6-接口隔离类
    设计模式--Note5--对象性能类
    设计模式--Note4--对象创建类
    设计模式--Note3--单一职责类
    设计模式--Note2--组件协作类
    V$ACCESS 查询结果慢的解决方法
    openstack numa详解(命令使用篇)
  • 原文地址:https://www.cnblogs.com/qianlifeng/p/2284119.html
Copyright © 2020-2023  润新知