昨天我遇到了一个问题。我被要求写一个休息服务,它暴露了一个类的所有属性。消费者都会消费不同的属性,在提交时,他们都会发送不同的子集。 例如,我们可以打电话给合同公司。
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,这将在映射到数据库类时覆盖数据。
答案 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;
}));