我正在制作一个 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 代码在这里
编译器似乎无法解析类“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
视为分隔符。希望可以帮到你。