可选的休息服务参数

时间:2016-03-09 09:16:42

标签: c# entity-framework rest json.net automapper

昨天我遇到了一个问题。我被要求写一个休息服务,它暴露了一个类的所有属性。消费者都会消费不同的属性,在提交时,他们都会发送不同的子集。 例如,我们可以打电话给合同公司。

class Company{
    public string Address {get;set;}
    public string CompanyNumber {get;set;}
    public string Turnover {get;set;}
    public string Employees {get;set;}
}

假设我们有两个已知系统要同步公司类。 系统1处理会计并希望阅读地址和更新营业额。 系统2处理hr并且想要读取地址并更新员工。 现在通常在面对这个问题时,人们会编写许多接口,每个接口都有一个适合终端系统的定制合同。但是我被告知这不是他们想要的。相反,如果属性是在JSON中提供的,则必须设置它。

问题是当从JSON反序列化类公司时,如果未提供属性,则属性为null,这将在映射到数据库类时覆盖数据。

1 个答案:

答案 0 :(得分:0)

我想出的解决方案是创建一个像Nullable这样的可选结构,但null也可以是有效值。 反序列化此结构时可以跟踪属性是否已设置,因此在JSON中提供。然后我可以在从DTO映射到数据库类时进行检查,并仅在设置属性时进行映射。:)

https://dotnetfiddle.net/QmHtSW

public interface IOptional
{
    bool HasBeenSet { get; }
}
public struct Optional<T> : IOptional
{

    internal readonly T Val;

    public Optional(T value)
    {
        Val = value;
        HasBeenSet = true;
    }

    public Optional(Optional<T> value)
    {
        Val = value.Value;
        HasBeenSet = value.HasBeenSet;
    }

    public bool HasBeenSet { get; }

    public override bool Equals(object obj)
    {
        return obj.Equals(Val);
    }
    public override int GetHashCode()
    {
        return Val.GetHashCode();
    }

    public static implicit operator T(Optional<T> optional)
    {
        return optional.Val;
    }

    public static implicit operator Optional<T>(T optional)
    {
        return new Optional<T>(optional);
    }

    public T Value => Val;
}

和我的AutoMapper映射配置文件

 CreateMap<TRestObject, TDomainObject>()
            .ForAllMembers(mo=>mo.Condition(f =>
            {
                var opt = f.SourceValue as IOptional;
                return opt==null || opt.HasBeenSet;
            }));