Установщик набора инструментов WPF для типа, определенного в другой сборке - PullRequest
6 голосов
/ 15 февраля 2011

Я пытаюсь создать установщик VSIX для элемента управления WPF.

Это предположительно просто, но в «легкой» версии предполагается, что вы создаете элемент управления WPF в проекте VSIX .

Дело в том, что мой UserControl расположен глубоко в одной из моих библиотек DLL, и я не верю, что его извлечение - лучший дизайн. Я бы хотел оставить это там, но я не могу этого сделать И добавить элемент управления на панель инструментов.

Один из вариантов - переместить код, необходимый для его установки, на панель инструментов в сборку элемента управления, но это добавит зависимость к Microsoft.VisualStudio.Shell.Immutable.10.0.dll . Сборка используется кем-то с установленной Visual Studio и удаленным сервером, работающим в службе, где VS не установлена, так что это не нужно.

Другой вариант, который я попробовал, заключался в том, чтобы «обмануть» установщик VSIX панели инструментов, применив атрибут RegistrationAttribute к прокси , который бы регистрировал типы, определенные в другой сборке. Думал, что это сработает, но случилось странное.

all kinds of weirdness in the toolbox

Вместо двух элементов управления я получаю набор элементов управления Border (стандартная граница WPF) на вкладках со странными именами, некоторые из которых перекликаются с некоторыми из моих пространств имен.

Как зарегистрировать WPF UserControl с помощью панели инструментов, если элемент управления определен в сборке, отличной от VSIX?

1 Ответ

2 голосов
/ 25 июня 2011

Мне удалось подготовить доказательство концепции, аналогичное идее прокси, которую вы упомянули.

Проблема, которую вы видите, вызвана регистрацией неправильной сборки, поэтому я создал новый атрибут регистрации с именем ProvideProxyToolboxControlAttribute, который используется в качестве атрибута прокси-классов, которые есть в вашей сборке интеграции VS. Он почти идентичен ProvideToolboxControlAttribute за исключением того, что он принимает тип фактического элемента управления. Конечно, этот новый атрибут также будет в вашей сборке VS.

Например, скажем, у меня есть набор инструментов в моей сборке без VS с именем MyToolboxControl, я бы создал простой прокси-класс MyToolboxControlProxy в моей сборке VS, который выглядит следующим образом:

[ProvideProxyToolboxControl("MyToolboxControl", typeof(NonVsAssembly.MyToolboxControl))]
public class ToolboxControlProxy
{
}

И, конечно, магия происходит в ProvideProxyToolboxControlAttribute, который в основном является именно этим классом (комментарии и проверка параметров / ошибок удалены для краткости):

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
[System.Runtime.InteropServices.ComVisibleAttribute(false)]
public sealed class ProvideProxyToolboxControlAttribute : RegistrationAttribute
{
    private const string ToolboxControlsInstallerPath = "ToolboxControlsInstaller";
    public ProvideProxyToolboxControlAttribute(string name, Type controlType)
    {
        this.Name = name;
        this.ControlType = controlType;
    }

    private string Name { get; set; }

    private Type ControlType { get; set; }

    public override void Register(RegistrationAttribute.RegistrationContext context)
    {
        using (Key key = context.CreateKey(String.Format(CultureInfo.InvariantCulture, "{0}\\{1}",
                                                         ToolboxControlsInstallerPath,
                                                         ControlType.AssemblyQualifiedName)))
        {
            key.SetValue(String.Empty, this.Name);
            key.SetValue("Codebase", ControlType.Assembly.Location);
            key.SetValue("WPFControls", "1");
        }
    }
    public override void Unregister(RegistrationAttribute.RegistrationContext context)
    {
        if (context != null)
        {
            context.RemoveKey(String.Format(CultureInfo.InvariantCulture, "{0}\\{1}",
                                                         ToolboxControlsInstallerPath,
                                                         ControlType.AssemblyQualifiedName));
        }
    }
}

Кажется, это работает хорошо, я проверил, что элемент управления находится в наборе инструментов и что были добавлены соответствующие ключи реестра.

Надеюсь, это поможет!

...