Как реализовать внедрение конструктора в приложение Xamarin Forms?

Я хотел бы создать приложение Xamarin, которое использует шаблон внедрения зависимостей. Моя текущая проблема заключается в том, что я просто не могу заставить его работать с xamarin каким-либо иным образом, кроме как в качестве анти-шаблона локатора зависимостей, в то время как мне нужна реальная инъекция конструктора. Я перепробовал все, что смог найти, от шаблонов Prism до tinyIoC, но ViewModels и Views просто требуют конструктора без параметров. Что мне не хватает?

Ниже приведены некоторые источники, которые были полезны, но не помогли решить мою проблему.

Мое приложение представляет собой свежий шаблон форм xamarin, созданный VS2019, я добавил только несколько библиотек, но они никоим образом не должны мешать. Xamarin явно предоставляет встроенный локатор зависимостей, но это не то, что я хотел использовать. Я также видел несколько шаблонов, которые достигли того, чего я хотел, но они были слишком большими, чтобы я мог понять, как именно они этого достигли.

В идеале я хотел бы использовать Microsoft MVVM Toolkit, но это не строгое требование. Я также хотел бы, чтобы реализация была максимально простой, так как я только начинаю разработку xamarin.

Пример того, чего бы я хотел добиться:

public class AboutViewModel : BaseViewModel
    {
        public AboutViewModel(ITest testService)
        {
            Title = "About";
            OpenWebCommand = new Command(async () => await Browser.OpenAsync("https://aka.ms/xamarin-quickstart"));
        }

        public ICommand OpenWebCommand { get; }
    }

    public interface ITest
    {
        void Test();
    }

    class TestService : ITest
    {
        public void Test()
        {
            Debug.WriteLine("Test successful");
        }
    }

person Luk164    schedule 18.06.2021    source источник


Ответы (1)


Хорошо, я узнал, что это есть в моем AboutPage.xaml

<ContentPage.BindingContext>
    <vm:AboutViewModel />
</ContentPage.BindingContext>

Похоже на простой способ инициализировать viewModel в представлении, за исключением того, что он может принимать только конструкторы без параметров. Это было причиной моих проблем. Перемещение инициализации ViewModel в код, стоящий за ним, решил все, хотя я все же предпочел бы просто передать его через конструктор codebehind. Вот результат:

public AboutPage()
{
    InitializeComponent();

    BindingContext = Ioc.Default.GetRequiredService<AboutViewModel>();
}
person Luk164    schedule 18.06.2021
comment
FWIW: Теперь, когда вы удалили xaml без параметров, который вызывал проблему. почему вы не можете передать его в качестве параметра? Во фрагменте кода вопроса отображается только ViewModel. В вашем ответе отображается только вид. Я не могу сказать из вашего вопроса, что вы хотели сделать, и я не могу сказать из вашего ответа, как это решило вашу проблему. В нынешнем виде эти вопросы и ответы никому не пригодятся. Было бы здорово, если бы вы добавили больше кода и в вопрос, и в ответ, чтобы показать, в чем проблема, и полное решение для нее! - person ToolmakerSteve; 19.06.2021
comment
Мне также непонятно, почему вы берете и без того сложную модель MVVM и добавляете еще один уровень сложности, выполняя инъекцию зависимостей. Практикуйте инкрементную разработку с рефакторингом. Найдите максимально простой код, который сделает то, что вам нужно сегодня. Не самый гибкий код - он почти всегда добавляет уровень косвенности или абстракции, который замедляет разработку. Самый простой и тупой код, который подойдет для текущих задач. AboutPage(AboutViewModel vm) { InitializeComponent(); BindingContext = vm;}. Использование: new AboutPage(new AboutviewModel(testService)); Готово. - person ToolmakerSteve; 19.06.2021
comment
@ToolmakerSteve В настоящее время я не могу просто вставить AboutVIewModel в AboutPage из-за способа вызова конструктора. Шаблон по умолчанию, кажется, просто вызывает его напрямую, и мне придется сначала исправить это, иначе это вызовет ту же проблему снова и снова, всего на один шаг выше. Может быть, когда у меня все наладится и будет работать так, как я хочу, я покажу, как я это сделал, но РН, боюсь, я вызову больше проблем, если начну редактировать вопрос. - person Luk164; 22.06.2021
comment
хорошо, нп. Наиболее ценным является то, что в вашем ответе показано оптимальное решение. Было бы здорово увидеть, что именно происходит. Какой шаблон по умолчанию вы имеете в виду? Три строки XAML вверху вашего ответа? Но вы удалили их сейчас, верно? Есть ли где-нибудь похожий XAML, который нелегко удалить? - person ToolmakerSteve; 22.06.2021
comment
@ToolmakerSteve В расширении Visual Studio Xamarin есть встроенный шаблон по умолчанию. Если вы его создадите, вы получите то же самое, что и я. - person Luk164; 22.06.2021
comment
В ПОРЯДКЕ. Но вам все равно придется вручную отредактировать, чтобы добавить свою строку кода в конструктор. Поэтому, если вы удалите эти три строки XAML, которые вы нашли, вы можете делать все, что захотите. Измените желаемый параметр. По какой причине не делать этого? - person ToolmakerSteve; 22.06.2021
comment
@ToolmakerSteve Видите ли, сам код AboutPage тоже должен иметь конструктор по умолчанию в этом шаблоне. Несмотря на то, что он не ограничен xaml, способ его вызова навигацией не поддерживает DI из коробки, насколько мне известно. Попробуйте и убедитесь сами, может быть, вам повезет больше, чем мне. - person Luk164; 22.06.2021