这是一个简化的ViewModel:

public class EditViewModel : BaseViewModel
{
    private Item _currentItem;
    public Item CurrentItem
    {
        get
        { return _currentItem; }
        set
        {
            if (_currentItem != value)
            {
                _currentItem = value;
                OnPropertyChanged("CurrentItem");
            }
        }
    }

    private ObservableCollection<Property> _itemProperties;
    public ObservableCollection<Property> ItemProperties
    {
        get { return _itemProperties; }
        set
        {
            _itemProperties = value;
            OnPropertyChanged("ItemProperties");
        }
    }

    public void AddProperty() //this is called from an ICommand
    {
        Property p = new Property{ ItemId = CurrentItem.ItemId };;
        CurrentItem.Properties.Add(p);
        ItemProperties.Add(p);
    }
}

我想做的是将这里的业务逻辑分离到一个单独的类中。它使所有烦人的MVVM样板都脱离了有用的内容,并且从理论上讲应导致将代码组织为更具可测试性的状态。

我们通过创建从BaseViewModel继承的单独的“Logic”类开始,然后从其逻辑类继承实际的ViewModel来开始这样做。所以:
public class EditLogic : BaseViewModel
{ }

public class EditViewModel : EditLogic
{ }

然后,逻辑进入逻辑类。

对于某些业务逻辑而言,这种分离很简单-干净利落。但是,在上面给出的示例中,我看不到没有很多不必要的麻烦的简单方法即可退出该方法。像这样(未经测试):
public class EditLogic : BaseViewModel
{
    public Property GetNewProperty(Item currentItem)
    {
        Property p = new Property{ ItemId = currentItem.ItemId };
        currentItem.Properties.Add(p);
        return p;
    }
}

public class EditViewModel : BaseViewModel
{
    public void AddProperty() //this is called from an ICommand
    {
        ItemProperties(GetNewProperty(CurrentItem))
    }
}

这似乎令人困惑-因为它依赖于CurrentItem隐式地通过引用传递-并且不必要地卷积而没有太大的收获。

当然,这是一个非常简单的示例,不值得大惊小怪。但是它说明了一点,在MVVM中,为方便起见,最终很容易将演示文稿/绑定(bind)代码与业务逻辑混合在一起。

我可以将某些属性从EditViewModel移到EditLogic,但是首先我们失去了将这两个属性分开的优势。

所以:值得为此烦恼吗?如果是这样,我们应该走多远?还有保持隔离的更好方法吗?

最佳答案

您正在寻找的是服务

public interface IPropertyService
{
    Property GetNewProperty(Item currentItem);
}

您当然需要一个实现:
public class MyPropertyService : IPropertyService
{
    public Property GetNewProperty(Item currentItem)
    {
        //TODO
    }
}

然后,您可以将此服务作为依赖项注入(inject)到 View 模型的构造函数中。
public class MyViewModel
{
    private IPropertyService _PropertyService;

    public MyViewModel(IPropertyService propertyService)
    {
        _PropertyService = propertyService;
    }

    public void AddProperty() //this is called from an ICommand
    {
        Property p = _PropertyService.GetProperty(CurrentItem);
        CurrentItem.Properties.Add(p);
        ItemProperties.Add(p);
    }
}

这将确保您不需要为业务逻辑创建大量的 View 模型基类。取而代之的是,将业务逻辑封装在服务中,然后将它们传递到依赖于它们的 View 模型中。

关于c# - MVVM中分离业务逻辑的距离,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33564054/

10-13 06:58