Создание OptionsProvider в отдельном проекте/библиотеке для проекта VSIX в расширении Visual Studio

Я делаю расширение 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. Кроме того, если бы существовал способ сделать это, это выглядело бы немного хаотично, поскольку модель представления должна иметь возможность создавать свой собственный экземпляр, полностью отдельный от представления. Признаюсь, я все еще немного озадачен тем, как правильно создавать модели представлений.

Код Github здесь

Любой совет ценится.

Могу ли я подтвердить, что вы столкнулись с ошибкой при создании этого проекта VisGit? Кажется, я не могу увидеть ошибку после создания VisGit на моей стороне.

Dou Xu-MSFT 25.06.2024 10:53

Привет еще раз, Доу. Вы пробовали конкретную ветку, указанную в ОП, поскольку у меня есть несколько веток для разных проблем.

stigzler 26.06.2024 12:11

Привет, Стигзлер, спасибо за напоминание. Я проигнорировал ветку. Выпишусь из соответствующей ветки на пробу.

Dou Xu-MSFT 27.06.2024 09:23
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Не удалось загрузить тип «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 🤷. Хорошо замечено и решено, Доу, спасибо.

stigzler 28.06.2024 14:38

Другие вопросы по теме