这个例子只使用了反射信息,并没有提到对于当前属性值得动态判断...
不知道你的需求是什么,感觉没必要啊。多一个属性就多一个呗,消费方就当不存在不用就是了。
这种根据值来动态决定有哪些属性只会带来一些不必要的麻烦。比如有些字段是null的,有些地方就想着给忽略掉,但是对于前端js来说,就有差异了,前者是null,后者则就是undefined了。
就是因为C#中只有有值和null值两种,才需要用忽略属性去表达undefined,否则就得用null加上ignore null去表达undefined,但是null又可以是null,就有歧义了。
总之就是C#没有办法同时表达null和undefined,所以我在想办法表达undefined(null就默认表达为null)。
至于为什么需要undefined,很简单的场景就是修改一个对象,用undefined表达不修改这个属性。
比如User有Company和Age两个属性,你只想修改Age而不想修改Company,那这个参数就可以是
{Age: 18}
Company是undefined就是表达忽略的语义。
@百香居士: 前端只修改age, 只发送这一个字段没问题。但是后端拿一个完整的class去做映射,这就不合适了,这会使得使得应用变得很“脆弱”(依赖隐含的逻辑来表达修改还是不修改),而且增加对对前端的要求(不能有多余的字段传输过来),两头都有假设(假设不传字段就是不修改)。这不太符合宽进严出的接口策略。
我的建议有2个方案:
选哪个都行。我认为还是1直观省事并且一致性强,而且没有任何的隐含的条件在里面。如果你担心每次修改多余的字段不合适,那么后端修改前查询出最新的数据,比对一下哪些需要修改就行了。看起来时麻烦了一些,但是没有隐含的假设的逻辑,也使得接口更加健壮。
@blackheart: 假设本来就是不可避免的,就是不知哪来的隐含一说。没有该字段即是忽略,是很明确也很明显的逻辑。即使没有“缺省即是忽略”,很多时候也都是定义为“缺省即是为空”,这对后端才是真正的隐含假设,不管是Newtonsoft还是.Net Core的Json库,默认设置都是如此。而且这种情况就不安全得多。
而“多余的字段”并不成立,如果前端将原值做为修改值传递,这就跟你说的方案1一样;如果前端将空值传递,那对于你的方案1来说,就是置空,对于我这个方案来说也是如此。所以对于一个动态字段的DTO,本身就是静态字段的DTO的超集,不存在做到静态做不到的事情,只是对静态语言的后端来说实现更复杂一些而已。我觉得相比之下,语义更清晰也更简洁,同时也不需要先查询后修改,节省开销。
后端也不会拿一个模型类去映射,而是每个可修改的字段都包了一层Option<T>在装进DTO里,是借用的函数式的概念,我现在就是在开发这个Option类型。