在不同程序集中定义的类型的WPF工具箱安装程序

在不同程序集中定义的类型的WPF工具箱安装程序,wpf,visual-studio,user-controls,installation,toolbox,Wpf,Visual Studio,User Controls,Installation,Toolbox,我正在尝试为WPF控件创建VSIX安装程序 它应该很简单,但是“简单”版本假设您在VSIX项目中创建了WPF控件 问题是,我已经把我的UserControl放在了我的一个DLL中,我不认为把它拔出来是最好的设计。我想把它留在那里,但我似乎不能这样做,并有控制添加到工具箱 一个选项是将安装到工具箱中所需的代码移动到控件的程序集中,但这会增加对Microsoft.VisualStudio.Shell.Immutable.10.0.dll的依赖关系。该程序集既可由安装了Visual Studio的用户

我正在尝试为WPF控件创建VSIX安装程序

它应该很简单,但是“简单”版本假设您在VSIX项目中创建了WPF控件

问题是,我已经把我的UserControl放在了我的一个DLL中,我不认为把它拔出来是最好的设计。我想把它留在那里,但我似乎不能这样做,并有控制添加到工具箱

一个选项是将安装到工具箱中所需的代码移动到控件的程序集中,但这会增加对Microsoft.VisualStudio.Shell.Immutable.10.0.dll的依赖关系。该程序集既可由安装了Visual Studio的用户使用,也可由未安装VS的服务中运行的远程服务器使用,因此这是不可能的

我尝试的另一个选项是通过将RegistrationAttribute应用于代理来“欺骗”工具箱安装程序VSIX,代理将注册在另一个程序集中定义的类型。我以为这会奏效,但奇怪的事情发生了

我没有得到两个控件,而是在命名奇怪的选项卡中得到了一堆边界控件(标准WPF边界),其中一些与我的一些名称空间相呼应


当WPF UserControl是在VSIX以外的程序集中定义的时,我如何向工具箱注册该控件?

我能够快速提出一个类似于您提到的代理思想的概念证明

您看到的问题是由于注册了错误的程序集引起的,因此我创建了一个名为
providedProxyToolboxControlAttribute
的新注册属性,该属性用作VS集成程序集中代理类的属性。它与providedToolboxControlAttribute几乎相同,只是它采用实际控件的类型。当然,这个新属性也将在VS程序集中

例如,假设我在非VS程序集中有一个名为
MyToolboxControl
的工具箱控件,我会在我的VS程序集中创建一个简单的代理类
MyToolboxControlProxy
,如下所示:

[ProvideProxyToolboxControl("MyToolboxControl", typeof(NonVsAssembly.MyToolboxControl))]
public class ToolboxControlProxy
{
}
当然,神奇之处在于
providedProxyToolboxControlAttribute
,它基本上就是这个类(为了简洁起见,删除了注释和参数/错误检查):

它似乎工作得很好,我验证了控件在工具箱中,并且添加了正确的注册表项


希望这有帮助

假设WPF控件必须在VSIX项目中,这一点在哪里?还有,你所说的“简单”版本是什么意思?@Matt:没有假设,只是工具是如何设计的。如果您按照MSDN演练进行操作,或者只查看已安装的模板,您将看到它面向(教程和模板)在同一项目中结合安装程序和控件。或者,你可以试着回答我的问题,在这种情况下,你会发现用其他方法做这件事并不容易。@我想我明白你的意思了吗,看起来你说的依赖关系就是ProvideToolboxControl属性?@Matt:是的。代理是VSIX中的类型,但我试图用它来注册其他程序集中定义的其他类型。@威尔,代理发生了什么奇怪的事情?我对我的自定义编辑器(其中核心控件位于另一个dll中)使用了类似的技巧。感谢您在这方面的帮助。大约需要一周左右的时间,我才能真正把它推出去,看看它对我是否有效。@will,我会说几年。
[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));
        }
    }
}