使用 MEF 扩展 .NET 应用程序中的菜单和上下文菜单
我正在尝试提出类似于 Visual Studio 2010 提供的菜单和上下文菜单体系结构,以便我可以使用扩展提供的其他子项来扩展当前菜单。我正在使用 MEF(托管扩展性框架)。 例如,Resharper 扩展在任何可能的位置(上下文菜单或菜单项的顶部、中间或底部)添加菜单项和上下文菜单项 如何才能提供这样的功能呢?我是否必须为 shell 的每个菜单项建立索引,并让扩展名引用索引以将其定位在子项上? 我希望我的问题足够清楚。如果没有,我将非常乐意添加一些说明。
I am trying to come up with a Menu and Context menu architecture similar to what Visual Studio 2010 offers so that I could extend my current Menu with additional subitems provided by extensions. I am using MEF (Managed Extensibility Framework).
As an example, the Resharper extension adds menu items and context menu items in any possible position (top, middle or bottom of the context menu or a menu item)
How could one go to provide such a functionality? Do I have to index every single menu item of the shell and have the extension refer to the index to position its on subitems?
I hope that my question is clear enough. If not I would be more than happy to add some clarification.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不确定是否有单一的最佳方法来做到这一点。但这里有一些需要考虑的想法:
一个相当简单的解决方案是使用单个合约(即 IMenuIten)并使用元数据来控制命令出现在哪个菜单中以及在什么位置。做到这一点的一种方法是有一个“索引”,尽管它可能应该是一个双精度值并用于对菜单中的项目进行排序,因此每个项目不需要知道其在菜单中的绝对位置。另一种方法是在菜单项上拥有元数据,该元数据给出了应位于当前项目之前和之后的其他项目的列表。然后,您可以对菜单项进行拓扑排序,以获得显示它们的顺序。
根据菜单行为需要的复杂/动态程度,您可能会发现无法使用导出元数据很好地表达它。在这种情况下,您可以将功能移至合约本身 - 即在 IMenuItem 合约上添加属性或方法。这样您就可以运行代码来计算您需要的值。
另一个解决方案是根本不直接导出菜单项。相反,您可以拥有由组件导入的菜单服务。该服务有一个 Register 方法,可以将菜单项添加到菜单中。在我看来,这使得添加菜单项变得相当麻烦,所以我不会推荐它,除非有你需要它的原因。如果可用的菜单项应根据应用程序的当前上下文进行更改,这可能是合适的。请注意,如果您确实这样做,则仅拥有一个导入菜单服务的类不会导致创建和组合该类。该类需要导出在系统其他地方导入的内容。
I'm not sure there's a single best way to do this. But here are some ideas to consider:
A fairly simple solution is to use a single contract (ie IMenuIten) and use metadata to control what menu the command appears in and in what position. One way to do this is to have an "index", although it should probably be a double and used to sort the items in a menu so each item doesn't need to know its absolute position in the menu. Another way is to have metadata on the menu items that gives a list of other items that should be before and after the current item. Then you can do a topological sort on the menu items to get an order to display them in.
Depending on how complex/dynamic your menu behavior needs to be, you may find that you can't express it well using export metadata. In this case you might move the functionality to the contract itself- ie adding properties or methods on your IMenuItem contract. That way you can run code to calculate the values you need.
Another solution is not to export menu items directly at all. Instead, you can have a menu service that is imported by a component. The service would have a Register method which would add a menu item to a menu. In my opinion this makes adding menu items quite a bit more cumbersome so I wouldn't recommend it unless there's a reason you need it. It might be appropriate if the available menu items should change based on the current context of the application. Note that if you do go this way, just having a class that imports the menu service won't cause the class to be created and composed. The class needs to export something that is imported somewhere else in the system.