C# 可选的Rest服务参数

C# 可选的Rest服务参数,c#,entity-framework,rest,json.net,automapper,C#,Entity Framework,Rest,Json.net,Automapper,昨天我遇到了一个问题。我被要求编写一个rest服务,它公开一个类的所有属性。消费者都会使用不同的属性,提交时都会发送不同的属性子集。 例如,让我们打电话给合同公司 class Company{ public string Address {get;set;} public string CompanyNumber {get;set;} public string Turnover {get;set;} public string Employees {get;se

昨天我遇到了一个问题。我被要求编写一个rest服务,它公开一个类的所有属性。消费者都会使用不同的属性,提交时都会发送不同的属性子集。 例如,让我们打电话给合同公司

class Company{
    public string Address {get;set;}
    public string CompanyNumber {get;set;}
    public string Turnover {get;set;}
    public string Employees {get;set;}
}
假设我们有两个已知的系统想要同步公司类。 系统1处理会计事务,希望读取地址并更新营业额。 系统2处理人力资源,希望读取地址并更新员工。 现在,当面临这个问题时,通常会编写大量的接口,每个接口都有一个定制的契约,以适应最终系统。然而,有人告诉我,这不是他们想要的。相反,如果属性是在JSON中提供的,则必须对其进行设置


问题是当从JSON反序列化类Company时,如果没有提供属性,那么属性为null,那么当映射到数据库类时,就会覆盖数据。

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

公共接口
{
bool HasBeenSet{get;}
}
公共结构可选:IOOptional
{
内部只读T值;
公共可选(T值)
{
Val=值;
HasBeenSet=true;
}
公共可选(可选值)
{
Val=值。值;
HasBeenSet=value.HasBeenSet;
}
公共布尔已被设置为{get;}
公共覆盖布尔等于(对象对象对象)
{
返回对象等于(Val);
}
公共覆盖int GetHashCode()
{
返回Val.GetHashCode();
}
公共静态隐式运算符T(可选)
{
返回可选的.Val;
}
公共静态隐式运算符可选(T可选)
{
返回新的可选(可选);
}
公共T值=>Val;
}
和我的自动映射配置文件

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

与之相关,将其制作成一个nuget包,并支持许多其他位
 CreateMap<TRestObject, TDomainObject>()
            .ForAllMembers(mo=>mo.Condition(f =>
            {
                var opt = f.SourceValue as IOptional;
                return opt==null || opt.HasBeenSet;
            }));