WPF:当视图模型和视图在单独的项目中如何做依赖注入?



我有这个MVVM模式的WPF应用程序,现在我想在我的项目中做依赖注入,但我发现自己遇到了麻烦。我的应用程序有以下结构:

MyApp
|----MyApp.ViewModels
|----MyApp.Views

根据这个文档,我需要在MyApp中的app . xml .cs文件中启动我的依赖注入服务。项目视图。

假设我在MyApp中有两个视图模型。视图模型项目:

public class ViewModelAlpha{
private IDialogService _dialogService;
private ViewModelBeta viewModelBeta;
public ViewModelAlpha(IDialogService dialogService){
_dialogService = dialogService;
}
}
public class ViewModelBeta{
private IDialogService _dialogService;
public ViewModelBeta(IDialogService dialogService){
_dialogService = dialogService;
}
}

因此,ViewModelAlpha有一个ViewModelBeta单例作为它的字段,我应该如何处理lazy initiateViewModelAlpha中的ViewModelBeta ?在需要之前,我不想初始化ViewModelBeta。我目前正在做的是提供一个静态的实例在ViewModelBeta:

public class ViewModelBeta{
private static ViewModelBeta instance;
public static ViewModelBeta Instance {
return instance ?? new ViewModelBeta();
}
public ViewModelBeta(){ ... }
}

我能想到的是把Instance属性改成这样:

public static ViewModelBeta Instance {
return instance ?? 
ServiceProvider.GetRequiredService<ViewModelBeta>();
}

但是由于ServiceProvider是在MyApp中创建的。视图项目,我应该如何得到它在MyApp。视图模型项目。

对于我遇到的一个类似的问题,对于一个类似的用例,我发现这个答案非常有用。

在DI中通用注册所有延迟加载的具体类型

最终的结果是你可以注册一个IYourInterface,它也会注册一个Func<IYourInterface>,你可以注入和调用当准备加载它。

所有的Func<T>做的是请求相同的接口从DI引擎,允许你延迟加载它。

在我的情况下,它注册了所有的Window类,我已经在我的程序集实现,但它可以应用于任何用例,方便的答案是一个很好的通用方式,利用表达式反射来组成Func<T>在飞行。

你可以看到,在我的另一个项目中,我扩展了这个功能,为ServiceCollection上的所有标准注册创建了一套类似的方法

https://github.com/SteffenBlake/PoeFilterX/blob/main/src/PoeFilterX/Extensions/ServiceCollectionExtensions.cs

我以前遇到过同样的问题,在构造函数中启动一些依赖关系可能需要额外的内存,在您的情况下,是视图模型。

一般来说,这个问题可能类似于transient在某些情况下,您将使用IServiceProvider.GetRequiredService<T>()来解决它们,然后很快删除它们的引用以减少内存消耗。 要使用服务提供者,最好的方法是将它作为依赖项注入到你的服务构造函数中,所以对于视图模型的情况:
public ViewModelAlpha(IDialogService dialogService, IServiceProvider serviceProvider)
{
_dialogService = dialogService;
_serviceProvider = serviceProvider;
}

然后你可以在需要的时候添加一个属性来延迟加载ViewModelBeta:

public class ViewModelAlpha
{
private ViewModelBeta? _viewModelBeta;
private ViewModelBeta ViewModelBeta
{
get => _viewModelBeta ??= _serviceProvider.GetRequiredService<ViewModelBeta>();
}

// Dependencies.
private IDialogService _dialogService;
private IServiceProvider _serviceProvider;
public ViewModelAlpha(IDialogService dialogService, IServiceProvider serviceProvider)
{
_dialogService = dialogService;
_serviceProvider = serviceProvider;
}
}

但是由于ServiceProvider是在MyApp中创建的。查看项目,如何我应该在MyApp中获取它吗?视图模型项目。

ServiceProvider注入到启动项目(MyApp.Views)中并不意味着核心库服务不能将其作为依赖项。事实上,将核心服务从启动项目中分离出来是一种常见的设计,它大声声明">任何需要我们服务的项目都必须首先为我们提供一些必要的依赖项&"。

这些依赖关系作为接口实现的一种形式是必需的,所以当核心库使用IMyService时,启动项目应该注入自己的IMyService实现,比如MyService

一个很好的例子是IHostApplicationLifetime服务,它是. net通用主机的一部分。在很多情况下,您可能希望从视图模型中关闭应用程序,为此您需要调用IHostApplicationLifetime.StopApplication()来完成这项工作。

最新更新