在 Visual Studio 扩展中的 VSIX 项目的单独项目/库中创建 OptionsProvider

问题描述 投票:0回答:1

我正在制作一个 VS 扩展来管理 Github 问题。由于

CommunityToolkit.MVVM
的一些特殊性以及 @Sergio0694 的建议,我不得不将我的 ViewModel、服务等分离到我的解决方案中的一个单独的项目中。因此,我还必须将我的 OptionsProvider(用于管理扩展的 VS>Tools>Options)移至附加库中,因为 ViewModel 和服务将严重依赖这些选项。

主 VSIX 项目

VisGit
将主工具窗口保存为名为
MainView
的视图。视图模型/服务等存在于一个单独的项目中,
VisGit.Core
。该视图纯粹通过 xaml 绑定到
MainViewModel
的实例(代码隐藏中没有任何内容):

<UserControl x:Class="VisGit.Views.MainView"
        xmlns:viewmodels="clr-namespace:VisGit.Core.ViewModels;assembly=VisGit.Core"/>
    <UserControl.DataContext>
        <viewmodels:MainViewModel />
    </UserControl.DataContext>

一切正常 - VisGit 包含对 VisGit.Core 的引用。我的 OptionsProvider 类位于 VisGit.Core 中。我必须首先在

VisGit
中创建它并移动它,因为“选项页面(社区)”在
VisGit.Core
中不可用,因为这只是一个标准类库。代码:

namespace VisGit.Core.Services
{
    public partial class OptionsProvider
    {
        // Register the options with this attribute on your package class:
        // [ProvideOptionPage(typeof(OptionsProvider.UserSettingsOptions), "VisGit.Services", "UserSettings", 0, 0, true, SupportsProfiles = true)]
        [ComVisible(true)]
        public class UserSettingsOptions : BaseOptionPage<UserSettings>
        { }
    }

    public class UserSettings : BaseOptionModel<UserSettings>
    {
        private string personalAccessToken = "{UNSET}";

        [DisplayName("Personal Access Token")]
        public string PersonalAccessToken
        {
            get => Encyption.DpapiToInsecureString(Encyption.DpapiDecryptString(personalAccessToken));
            set => personalAccessToken = Encyption.DpapiEncryptString(Encyption.DpapiToSecureString(value));
        }
    }
}

我在

Community.VisualStudio.Toolkit.17
中引用了
VisGit.Core
。现在,因为它不在 VSIX 项目中,所以我修改了样板说明,使其指向
VisGitPackage.cs
文件中 UserSettings 的正确位置:
VisGit

namespace VisGit
{
    [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
    [InstalledProductRegistration(Vsix.Name, Vsix.Description, Vsix.Version)]
    [ProvideToolWindow(typeof(MainToolWindow.Pane), Style = VsDockStyle.Tabbed, Window = WindowGuids.SolutionExplorer)]
    [ProvideMenuResource("Menus.ctmenu", 1)]
    [Guid(PackageGuids.VisGitString)]
    [ProvideOptionPage(typeof(VisGit.Core.Services.OptionsProvider.UserSettingsOptions), "VisGit.Core.Services", "UserSettings", 0, 0, true, SupportsProfiles = true)]
    public sealed class VisGitPackage : ToolkitPackage
    {
        protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
        {
            await this.RegisterCommandsAsync();

            this.RegisterToolWindows();
        }
    }
}

可以编译,但

VisGit.Core
不能编译。我得到了令人费解的错误:
VisGit

我确实注意到 
Error CreatePkgDef : error : TypeLoadException: Could not load type 'VisGit.Core.Services.OptionsProvider+UserSettingsOptions' from assembly 'VisGit.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. at System.Reflection.CustomAttribute._CreateCaObject(RuntimeModule pModule, IRuntimeMethodInfo pCtor, Byte** ppBlob, Byte* pEndBlob, Int32* pcNamedArgs) at System.Reflection.CustomAttribute.CreateCaObject(RuntimeModule module, IRuntimeMethodInfo ctor, IntPtr& blob, IntPtr blobEnd, Int32& namedArgs) at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType, Boolean mustBeInheritable, IList derivedAttributes, Boolean isDecoratedTargetSecurityTransparent) at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeType type, RuntimeType caType, Boolean inherit) at Microsoft.VisualStudio.Tools.CreatePkgDef.ProcessAssembly(String fileName, Hive hive, PkgDefContext context, Boolean register, RegistrationMode mode) in D:\a\_work\1\s\src\product\vssdk\tools\CreatePkgDef\CreatePkgDef.cs:line 341 at Microsoft.VisualStudio.Tools.CreatePkgDef.DoCreatePkgDef(InputArguments inputArguments) in D:\a\_work\1\s\src\product\vssdk\tools\CreatePkgDef\CreatePkgDef.cs:line 202 at Microsoft.VisualStudio.Tools.CreatePkgDef.Main(String[] arguments) in D:\a\_work\1\s\src\product\vssdk\tools\CreatePkgDef\CreatePkgDef.cs:line 91 VisGit

类是部分的,但是如果我在 VSIX 项目中创建一个新的 OptionsProvider,并尝试在类名上“转到定义”,我找不到该类的任何其他定义(即没有其他部分)。

使用目前的架构,我无法实例化 VSIX 项目 (VisGit) 中的 UserOptions 并将它们传递给任何视图模型,因为 ViewModel 是在视图 XAML 中实例化的。此外,如果有办法做到这一点,感觉有点hacky,因为视图模型应该能够创建自己的实例以与视图完全分离。不可否认,我仍然对如何正确实例化视图模型感到有点困惑。

Github 代码在这里

任何建议表示赞赏。

wpf settings visual-studio-extensions
1个回答
0
投票
无法从程序集“VisGit.Core,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”加载类型“VisGit.Core.Services.OptionsProvider+UserSettingsOptions”

编译器似乎无法解析类“VisGit.Core.Services.OptionsProvider+UserSettingsOptions”。检查目录结构后,看起来您的
OptionsProvider

文件夹位于名称空间

service
下。命名空间的名称必须是有效的
C# 标识符名称
请尝试删除命名空间中的点(“.”)

VisGit.Core

并将其重命名为

VisGit.Core
。 例如
VisGitCore

这样做之后,我能够构建
[ProvideOptionPage(typeof(VisGitCore.Services.OptionsProvider.UserSettingsOptions), "VisGitCore.Services", "UserSettings", 0, 0, true, SupportsProfiles = true)]

,没有错误。

我认为,由于 

Namespaces

是使用 VisGit 运算符分隔的,但如果

.
的名称包含点,它会将
Nampespace
视为分隔符。
希望可以帮到你。

© www.soinside.com 2019 - 2024. All rights reserved.