一个WPF工具箱安装程序,用于在不同程序集中定义的类型。

6
我正在尝试为一个WPF控件创建VSIX安装程序。这似乎很容易,但是“简单”版本假设您在VSIX项目中创建了WPF控件。
问题是,我的UserControl深嵌在一个DLL中,我认为将其拆分出来并不是最好的设计。我想让它留在那里,但我似乎无法这样做,并且使控件添加到工具箱。
其中一种选择是将我需要安装到工具箱的代码移动到控件的程序集中,但这将添加对Microsoft.VisualStudio.Shell.Immutable.10.0.dll的依赖项。该程序集既被安装了Visual Studio的用户使用,也被运行在服务内的远程服务器使用,而没有安装VS,所以这是不可行的。
我尝试的另一个选项是通过将RegistrationAttribute应用于代理来欺骗工具箱安装程序VSIX,这将注册在其他程序集中定义的类型。我认为它会起作用,但出现了奇怪的事情。
与其得到两个控件,我得到了一堆边框控件(标准WPF边框),它们在奇怪命名的选项卡中,其中一些回显了我的某些命名空间。
当控件的定义在VSIX之外的程序集中时,如何将WPF UserControl注册到工具箱?

WPF控件必须在VSIX项目中的假设在哪里?此外,“易用”版本是什么意思? - Matt
1
@Matt:没有假设,只是工具的设计。如果您按照MSDN演示文稿此处此处或查看已安装的模板,您将看到它面向(教程和模板)在同一项目中合并安装程序和控件。或者,您可以尝试回答我的问题,那么您会发现以其他任何方式完成这项任务都不是容易的。 - user1228
@Will,我想我明白你的意思了,看起来ProvideToolboxControl属性就是你所说的依赖关系? - Matt
@Matt:是的。代理是在VSIX中定义的类型,但我尝试使用它们来注册其他程序集中定义的类型。 - user1228
哦,谢谢!我明天会试试看。 - rPulvi
显示剩余4条评论
1个回答

2
我能够制作一个类似于你提到的代理想法的概念验证。你看到的问题是由于注册了错误的程序集引起的,因此我创建了一个名为ProvideProxyToolboxControlAttribute的新注册属性,它被用作代理类的属性,这些代理类在您的VS集成程序集中。它几乎与ProvideToolboxControlAttribute相同,只是它需要实际控件的类型。当然,这个新属性也将在您的VS程序集中。 例如,假设我在我的非VS程序集中有一个工具箱控件叫做MyToolboxControl,我会在我的VS程序集中创建一个简单的代理类MyToolboxControlProxy,它看起来像这样:
[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));
        }
    }
}

看起来这个功能运行良好,我验证了控件是否在工具箱中,并且适当的注册表键已经添加。

希望这能有所帮助!


感谢您的帮助。在我实际应用并查看其是否适用于我的情况之前,可能需要一周左右的时间。 - user1228
@Will 我会说大约几年。 - Niki Romagnoli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接