我对Avalonia/WPF、Xaml和桌面开发都很陌生,请谅解,如有误解请指正。我将继续学习相关文档,但是在找到能解决我的问题的材料方面遇到了困难。
我正在尝试在我的Avalonia应用程序中实现一个基于组合根、构造函数注入的依赖注入系统,使用推荐的MVVM模式和相应的Avalonia项目模板。我对Microsoft.Extensions.DependencyInjection包有一定的熟悉度,因此一直在尝试使用这个系统。
通过基于这个DI框架以及其他框架的教程,我试图拼凑出一个可行的解决方案。我认为我已经理解了如何注册服务和ViewModel,并适当地设置这些类的构造函数,以便框架会在实例化这些类时注入依赖项。然而,我卡在了如何为View类实现构造函数注入上。
我尝试将MainWindow和MainWindowViewModel都注册为服务:
// App.axaml.cs
public partial class App : Application
{
private IServiceProvider _services;
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
ConfigureServiceProvider();
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = _services.GetService<MainWindow>();
}
base.OnFrameworkInitializationCompleted();
}
private void ConfigureServiceProvider()
{
var services = ConfigureServices();
_services = services.BuildServiceProvider();
}
private static IServiceCollection ConfigureServices()
{
var services = new ServiceCollection();
services.AddTransient<MainWindow>();
services.AddTransient<MainWindowViewModel>();
return services;
}
}
目标是通过构造函数将MainWindowViewModel类注入到MainWindow类中,然后将该参数分配给MainWindow视图类的DataContext属性:
// MainWindow.axaml.cs
public partial class MainWindow : Window
{
public MainWindow(MainWindowViewModel viewModel)
{
DataContext = viewModel;
InitializeComponent();
#if DEBUG
this.AttachDevTools();
#endif
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
然而,这会引发以下错误:
MainWindow.axaml(1, 2): [XAMLIL] Unable to find public constructor for type MyApp.Client:MyApp.Client.Views.MainWindow() Line 1, position 2.
看起来没有无参构造函数的情况下无法实例化View,但这似乎会阻止构造函数注入。
我可能对ViewModels和Views之间预期的关系有些基本误解。我遇到了一些示例,其中ViewModels未在服务容器中注册,而是直接在View构造函数中实例化并分配给DataContext属性。我希望避免这种方法。
同时,我遇到的每个教程都演示了将ViewModels通过构造函数注入到相应的View类中的方法,但它们都使用了服务定位器模式,其中DI服务容器被显式传递(或作为全局对象调用),并且ViewModels从容器中显式地解析出来。
请问是否有人可以提供任何演示如何通过构造函数正确注入ViewModels到Views的示例源代码或教程?这可行吗?是否可以修改MainWindow.axaml文件以启用所需行为?谢谢您的时间,再次感谢向我澄清可能存在的误解。
仅供参考,此处是MainWindow的标记:
// MainWindow.axaml
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:MyApp.Client.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="MyApp.Client.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
x:CompileBindings="True"
Icon="/Assets/avalonia-logo.ico"
Title="MyApp">
<TextBlock Text="{Binding Greeting}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Window>