C# 优雅地处理基类依赖关系
在我正在处理的项目中,我添加了一个基本的ViewModel类,它包含了所有ViewModels通用的一些功能和依赖项。它通过以下属性提供验证、消息传递、调度和导航服务:C# 优雅地处理基类依赖关系,c#,dependency-injection,C#,Dependency Injection,在我正在处理的项目中,我添加了一个基本的ViewModel类,它包含了所有ViewModels通用的一些功能和依赖项。它通过以下属性提供验证、消息传递、调度和导航服务: IValidateProperties Validator { get; } IMessenger Messenger { get; } IDispatcherHelper DispatcherHelper { get; } INavigationService Navigation { get; } 我使用IoC容器连接我的
IValidateProperties Validator { get; }
IMessenger Messenger { get; }
IDispatcherHelper DispatcherHelper { get; }
INavigationService Navigation { get; }
我使用IoC容器连接我的依赖项,但是我有几个选项来处理这些依赖项,这些依赖项对于我的所有ViewModels都是通用的:
private IValidateProperties _validator;
public IValidateProperties Validator
{
get => _validator;
set
{
_validator = value;
_validator.ValidationTarget = this;
}
}
private IMessenger _messenger;
public IMessenger Messenger
{
get => _messenger;
set
{
_messenger = value;
MessengerAttached();
}
}
protected virtual void MessengerAttached() { }
Messenger
、DispatcherHelper
和Navigation
来说很容易,因为它们都是作为单例使用的。对于验证器
,我需要添加一个静态验证器工厂
,并使用工厂在构造函数中实例化验证器
。这种方式似乎是做事情最干净的方式,但我脑海中有这样一种声音告诉我,使用这样的静力学是个坏主意public abstract class ViewModelTestBase
{
protected readonly IValidateProperties ValidatorMock;
protected readonly IMessenger MessengerMock;
protected readonly IDispatcherHelper DispatcherHelperMock;
protected readonly INavigationService NavigationMock;
protected ViewModelTestBase()
{
ValidatorMock = Substitute.For<IValidateProperties>();
ViewModelBase.Validator = ValidatorMock;
MessengerMock = Substitute.For<IMessenger>();
ViewModelBase.Messenger = MessengerMock;
DispatcherHelperMock = Substitute.For<IDispatcherHelper>();
ViewModelBase.DispatcherHelper = DispatcherHelperMock;
NavigationMock = Substitute.For<INavigationService>();
ViewModelBase.Navigation = NavigationMock;
}
}
公共抽象类ViewModelTestBase
{
受保护的只读IValidateProperties;
受保护的只读IMessenger Messenger Mock;
受保护的只读IDispatcherHelper DispatcherHelper DispatcherHelperLock;
受保护的只读INavigationService NavigationMock;
受保护的ViewModelTestBase()
{
ValidatorMock=替换.For();
ViewModelBase.Validator=ValidatorMock;
Messenger mock=替换为();
ViewModelBase.Messenger=MessengerMock;
DispatcherHelperMock=替换.For();
ViewModelBase.DispatcherHelper=DispatcherHelperMock;
NavigationMock=替换.For();
ViewModelBase.Navigation=NavigationMock;
}
}
那么,不采用第三种方法的具体原因是什么?如果静力学在这种情况下真的是个糟糕的主意,那么有什么具体的理由不使用方法2呢 非常基于意见的问题。。。这是我的1,2,3:使用1,因为这是使用IOC的代码通常期望的方法。很可能没有人会期望IOC为3设置静态属性,而对于2,虽然这是合理的,但感觉您在特定用例的调用时间方面已经存在一些问题(可能试图在构造函数中使用这些属性)…我使用的IOC容器进行属性注入,因此它与选项2一起工作。选项3意味着我必须在应用程序启动时手动设置它们的值,而不是使用IoC容器,但老实说,我对此并不太满意,因为我只需要做一次。我想知道是否真的有什么具体的理由不使用选项3。我希望问题是相反的-什么是使用静态。。。假设您在编写WPF代码时没有进行任何测试,并且永远不会使用多线程或转向编写ASP.Net(或其他可能并行处理多个请求的代码)-您可能有很好的理由坚持使用静态。。。您可能需要阅读或其他一些搜索结果,以获取我推荐的#1。使用静态使代码不容易测试,这与使用依赖项注入的主要原因之一背道而驰。是的,这将是一些额外的样板代码,但它很容易编写。您可以创建一个facade服务,如
ViewModelManager
,它封装了所有这些常见的依赖项,因此您只需处理视图模型构造函数的一个额外参数。这也可以避免在以后创建另一个依赖项时向视图模型构造函数添加额外的参数。#1也是我的建议。有关说明和详细信息,请参阅。这也适用于未来的更改和增强,只需很少的努力。非常基于意见的问题。。。这是我的1,2,3:使用1,因为这是使用IOC的代码通常期望的方法。很可能没有人会期望IOC为3设置静态属性,而对于2,虽然这是合理的,但感觉您在特定用例的调用时间方面已经存在一些问题(可能试图在构造函数中使用这些属性)…我使用的IOC容器进行属性注入,因此它与选项2一起工作。选项3意味着我必须在应用程序启动时手动设置它们的值,而不是使用IoC容器,但老实说,我对此并不太满意,因为我只需要做一次。我想知道是否真的有什么具体的理由不使用选项3。我希望问题是相反的-什么是使用静态。。。假设您在编写WPF代码时没有进行任何测试,并且永远不会使用多线程或转向编写ASP.Net(或其他可能并行处理多个请求的代码)-您可能有很好的理由坚持使用静态。。。你可能想要阅读或其他一些东西