Я не уверен, что есть лучший способ сделать это. Но вот несколько идей для рассмотрения:
Довольно простое решение состоит в том, чтобы использовать один контракт (т. Е. IMenuIten) и использовать метаданные для управления тем, в каком меню появляется команда и в какой позиции. Один из способов сделать это - иметь индекс, хотя он, вероятно, должен быть двойным и использоваться для сортировки элементов в меню, чтобы каждому элементу не нужно было знать его абсолютную позицию в меню. Другой способ заключается в том, чтобы иметь метаданные в пунктах меню, которые дают список других элементов, которые должны быть до и после текущего элемента. Затем вы можете выполнить топологическую сортировку пунктов меню, чтобы получить порядок их отображения.
В зависимости от того, насколько сложным / динамичным должно быть ваше поведение в меню, вы можете обнаружить, что вы не можете выразить его с помощью метаданных экспорта. В этом случае вы можете переместить функциональность в сам контракт, т. Е. Добавить свойства или методы в свой контракт IMenuItem. Таким образом, вы можете запустить код для вычисления необходимых вам значений.
Другое решение - не экспортировать пункты меню напрямую. Вместо этого вы можете иметь службу меню, которая импортируется компонентом. Служба будет иметь метод Register, который будет добавлять пункт меню в меню. По моему мнению, это делает добавление пунктов меню немного более громоздким, поэтому я бы не рекомендовал его, если бы не была причина, по которой он вам нужен. Возможно, будет целесообразно изменить доступные пункты меню в зависимости от текущего контекста приложения. Обратите внимание, что если вы пойдете по этому пути, просто наличие класса, который импортирует службу меню, не приведет к тому, что класс будет создан и составлен. Класс должен экспортировать то, что импортировано где-то еще в системе.