Я делаю расширение VS для управления проблемами Github. Из-за некоторых особенностей CommunityToolkit.MVVM
и по совету @Sergio0694 мне пришлось выделить модели ViewModels, Services и т. д. в отдельный проект в моем решении. Из-за этого мне также пришлось переместить мой OptionsProvider (который управляет VS>Tools>Options для расширения) в дополнительную библиотеку, поскольку ViewModels и Services будут в значительной степени полагаться на эти параметры.
Основной проект VSIX VisGit
содержит основное окно ToolWindow в виде представления под названием MainView
. Модели просмотра/сервисы и т. д. существуют в отдельном проекте, VisGit.Core
. Это представление привязано к экземпляру MainViewModel
исключительно через xaml (ничего в коде):
<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, я исправил шаблонные инструкции, чтобы указать правильное место для UserSettings в моем файле VisGitPackage.cs
в 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
Я отмечаю, что класс OptionsProvider
является частичным, но если я создам новый OptionsProvider в проекте VSIX и попытаюсь «Перейти к определению» по имени класса, я не смогу найти никакого другого определения для этого класса (т. е. никакого другого определения). частичный).
При нынешней архитектуре я не могу создать экземпляр UserOptions в проекте VSIX (VisGit) и передать их в любые модели представления, поскольку экземпляры ViewModels создаются в представлении XAML. Кроме того, если бы существовал способ сделать это, это выглядело бы немного хаотично, поскольку модель представления должна иметь возможность создавать свой собственный экземпляр, полностью отдельный от представления. Признаюсь, я все еще немного озадачен тем, как правильно создавать модели представлений.
Любой совет ценится.
Привет еще раз, Доу. Вы пробовали конкретную ветку, указанную в ОП, поскольку у меня есть несколько веток для разных проблем.
Привет, Стигзлер, спасибо за напоминание. Я проигнорировал ветку. Выпишусь из соответствующей ветки на пробу.
Не удалось загрузить тип «VisGit.Core.Services.OptionsProvider+UserSettingsOptions» из сборки «VisGit.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null»).
Кажется, что компилятор не может проанализировать класс VisGit.Core.Services.OptionsProvider+UserSettingsOptions. После проверки структуры каталогов выяснилось, что ваша папка service
находится под именами VisGit.Core
. Имя пространства имен должно быть допустимым именем идентификатора C#.
Пожалуйста, попробуйте удалить точку(".") в пространстве имен VisGit.Core
и переименуйте ее в VisGitCore
.
Например
[ProvideOptionPage(typeof(VisGitCore.Services.OptionsProvider.UserSettingsOptions), "VisGitCore.Services", "UserSettings", 0, 0, true, SupportsProfiles = true)]
После этого я могу построить VisGit
нормально без ошибок.
Я думаю, что Пространства имен разделяются с помощью оператора .
, но если имя Nampespace
содержит точки, оно будет рассматривать .
как разделитель.
Надеюсь, это поможет вам.
Спасибо, Доу. Это сделало это. Просто для тех, кто оказался в такой ситуации, вам нужно «опустить точку» как для пространства имен, так и для имени сборки. Странная ошибка, поскольку никогда раньше не возникало такой проблемы с пунктирными именами проектов/сборок/пространств имен, и это очень распространенная практика. Думаю, это просто еще одна особенность разработки VISX 🤷. Хорошо замечено и решено, Доу, спасибо.
Могу ли я подтвердить, что вы столкнулись с ошибкой при создании этого проекта
VisGit
? Кажется, я не могу увидеть ошибку после созданияVisGit
на моей стороне.