从C#中的其他对象属性历史记录更新对象以实现PATCH

时间:2015-08-20 16:45:33

标签: c# asp.net .net rest lambda

我试图在Web API上为将存储在DB中的对象实现PATCH。来自控制器的输入对象具有可以修改的所有属性,但我们允许客户端选择要发回的字段。如果某些字段已更改或已设置,我们只想更新MongoDB表示。我们开始使用Dirty对象模式(不确定这是一个模式),当你设置一个属性时,你也会记录它是脏的。例如

public class Example
{
    private string _title;
    public string Title 
    { 
        get { return _title; }
        set 
        { 
             _title = value;
            TitleWasSet = true;
        } 
    }
    public bool TitleWasSet {get;set;}
}

这可行,但有点乏味,我觉得它暴露了许多可以包含的逻辑。

因此,我提出的解决方案是将更新操作存储在入站对象中,然后以Try Update方式将它们重新应用于Mongo对象。

像这样:

public class Data
{
    public string Header { get; set; }
    public int Rating { get; set; }
}

public class EditDataRequest
{
    private readonly List<Action<Data>> _updates;

    public EditDataRequest()
    {
        _updates = new List<Action<Data>>();
    }

    public string Header
    {
        set
        {
            _updates.Add(data => {data.Header = value;});
        }
    }
    public int Rating
    {
        set
        {
            _updates.Add(data => {data.Rating = value;});
        }
    }

    public bool TryUpdateFromMe(Data original)
    {
        if (_updates.Count == 0)
            return false;
        foreach (var update in _updates)
        {
            update.Invoke(original);
        }

        return true;
    }
}

现在这会很好用,但它没有考虑到相同的值。所以我然后考虑将操作列表更改为一个函数列表,如果值存在差异则返回bool。

private readonly List<Func<Data, bool>> _updates;

然后属性看起来像这样:

    public int Rating
    {
        set
        {
            _updates.Add(data => {
                if (data.Rating != value)
                {
                    data.Rating = value;
                    return true;
                }
                return false;
            });
        }
    }

尝试更新方法......

        public bool TryUpdateFromMe(Data original)
        {
            if (_updates.Count == 0)
                return false;
            bool changesRequired = false;
            foreach (var update in _updates)
            {
                changesRequired |=  update.Invoke(original);
            }

            return changesRequired;
        }

正如您所看到的,属性集实现相当笨重,并且会使代码难以阅读。

我想要一种提取检查此属性值的方法,然后将其更新为另一种我可以在每个属性中重用的方法 - 我认为这可能是某种方式,但可能不是。

当然,如果您对如何处理PATCH情况有更好的建议,那么我也很乐意听到它们。

感谢您阅读此内容。

0 个答案:

没有答案