📅  最后修改于: 2020-11-19 05:26:09             🧑  作者: Mango
在本章中,我们将简要讨论依赖注入。我们已经介绍了将视图和ViewModel彼此分离的数据绑定,这些视图使View和ViewModel可以进行通信,而无需明确知道通信另一端的情况。
现在,我们需要类似的东西来将ViewModel与客户端服务分离。
在面向对象编程的早期,开发人员面临着在应用程序中创建和检索类实例的问题。针对该问题已经提出了各种解决方案。
在过去的几年中,依赖注入和控制反转(IoC)在开发人员中越来越流行,并且优先于某些较旧的解决方案,例如Singleton模式。
IoC和依赖项注入是两个紧密相关的设计模式,而容器基本上是一堆基础结构代码,可以为您完成这两种模式。
IoC模式是关于委派构造的责任,而依赖项注入模式是关于为已经构造的对象提供依赖性。
它们都可以视为构建的两阶段方法。使用容器时,该容器承担以下几项职责:
让我们看一下如何使用依赖注入来打破ViewModel和客户端服务之间的解耦。我们将使用与此相关的依赖项注入来连接保存处理AddEditCustomerViewModel表单。
首先,我们需要在“服务”文件夹中的项目中创建一个新界面。如果您的项目中没有服务文件夹,请先创建它,然后在“服务”文件夹中添加以下界面。
using MVVMHierarchiesDemo.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MVVMHierarchiesDemo.Services {
public interface ICustomersRepository {
Task> GetCustomersAsync();
Task GetCustomerAsync(Guid id);
Task AddCustomerAsync(Customer customer);
Task UpdateCustomerAsync(Customer customer);
Task DeleteCustomerAsync(Guid customerId);
}
}
以下是ICustomersRepository的实现。
using MVVMHierarchiesDemo.Model;
using System;
using System.Collections.Generic;
using System.Linq; using System.Text;
using System.Threading.Tasks;
namespace MVVMHierarchiesDemo.Services {
public class CustomersRepository : ICustomersRepository {
ZzaDbContext _context = new ZzaDbContext();
public Task> GetCustomersAsync() {
return _context.Customers.ToListAsync();
}
public Task GetCustomerAsync(Guid id) {
return _context.Customers.FirstOrDefaultAsync(c => c.Id == id);
}
public async Task AddCustomerAsync(Customer customer){
_context.Customers.Add(customer);
await _context.SaveChangesAsync();
return customer;
}
public async Task UpdateCustomerAsync(Customer customer) {
if (!_context.Customers.Local.Any(c => c.Id == customer.Id)) {
_context.Customers.Attach(customer);
}
_context.Entry(customer).State = EntityState.Modified;
await _context.SaveChangesAsync();
return customer;
}
public async Task DeleteCustomerAsync(Guid customerId) {
var customer = _context.Customers.FirstOrDefault(c => c.Id == customerId);
if (customer != null) {
_context.Customers.Remove(customer);
}
await _context.SaveChangesAsync();
}
}
}
执行保存处理的简单方法是在AddEditCustomerViewModel中添加ICustomersRepository的新实例,并重载AddEditCustomerViewModel和CustomerListViewModel构造函数。
private ICustomersRepository _repo;
public AddEditCustomerViewModel(ICustomersRepository repo) {
_repo = repo;
CancelCommand = new MyIcommand(OnCancel);
SaveCommand = new MyIcommand(OnSave, CanSave);
}
如下面的代码所示,更新OnSave方法。
private async void OnSave() {
UpdateCustomer(Customer, _editingCustomer);
if (EditMode)
await _repo.UpdateCustomerAsync(_editingCustomer);
else
await _repo.AddCustomerAsync(_editingCustomer);
Done();
}
private void UpdateCustomer(SimpleEditableCustomer source, Customer target) {
target.FirstName = source.FirstName;
target.LastName = source.LastName;
target.Phone = source.Phone;
target.Email = source.Email;
}
以下是完整的AddEditCustomerViewModel。
using MVVMHierarchiesDemo.Model;
using MVVMHierarchiesDemo.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MVVMHierarchiesDemo.ViewModel {
class AddEditCustomerViewModel : BindableBase {
private ICustomersRepository _repo;
public AddEditCustomerViewModel(ICustomersRepository repo) {
_repo = repo;
CancelCommand = new MyIcommand(OnCancel);
SaveCommand = new MyIcommand(OnSave, CanSave);
}
private bool _EditMode;
public bool EditMode {
get { return _EditMode; }
set { SetProperty(ref _EditMode, value); }
}
private SimpleEditableCustomer _Customer;
public SimpleEditableCustomer Customer {
get { return _Customer; }
set { SetProperty(ref _Customer, value); }
}
private Customer _editingCustomer = null;
public void SetCustomer(Customer cust) {
_editingCustomer = cust;
if (Customer != null) Customer.ErrorsChanged -= RaiseCanExecuteChanged;
Customer = new SimpleEditableCustomer();
Customer.ErrorsChanged += RaiseCanExecuteChanged;
CopyCustomer(cust, Customer);
}
private void RaiseCanExecuteChanged(object sender, EventArgs e) {
SaveCommand.RaiseCanExecuteChanged();
}
public MyIcommand CancelCommand { get; private set; }
public MyIcommand SaveCommand { get; private set; }
public event Action Done = delegate { };
private void OnCancel() {
Done();
}
private async void OnSave() {
UpdateCustomer(Customer, _editingCustomer);
if (EditMode)
await _repo.UpdateCustomerAsync(_editingCustomer);
else
await _repo.AddCustomerAsync(_editingCustomer);
Done();
}
private void UpdateCustomer(SimpleEditableCustomer source, Customer target) {
target.FirstName = source.FirstName;
target.LastName = source.LastName;
target.Phone = source.Phone;
target.Email = source.Email;
}
private bool CanSave() {
return !Customer.HasErrors;
}
private void CopyCustomer(Customer source, SimpleEditableCustomer target) {
target.Id = source.Id;
if (EditMode) {
target.FirstName = source.FirstName;
target.LastName = source.LastName;
target.Phone = source.Phone;
target.Email = source.Email;
}
}
}
}
当上面的代码被编译和执行时,您将看到相同的输出,但是现在ViewModels更松散地分离了。
当您按添加客户按钮时,您将看到以下视图。当用户将任何字段留空时,该字段将突出显示,并且保存按钮将被禁用。