C# 实现抽象基字段时在序列化期间继承属性
我有一个抽象类C# 实现抽象基字段时在序列化期间继承属性,c#,.net,system.text.json,C#,.net,System.text.json,我有一个抽象类Base,它希望每个派生类实现一个属性SortValue。此属性应具有应用于所有派生实例的属性,在本例中为JsonIgnore 发生的情况似乎是派生的不尊重该属性。至少,当通过System.Text.Json序列化时,不会忽略该属性 如何在确保每个子类实现SortValue的同时实现属性继承 public abstract class Base { [JsonIgnore] public abstract IComparable SortValue { get; }
Base
,它希望每个派生类实现一个属性SortValue
。此属性应具有应用于所有派生实例的属性,在本例中为JsonIgnore
发生的情况似乎是派生的
不尊重该属性。至少,当通过System.Text.Json序列化时,不会忽略该属性
如何在确保每个子类实现SortValue
的同时实现属性继承
public abstract class Base
{
[JsonIgnore]
public abstract IComparable SortValue { get; }
}
public class Derived : Base
{
public int VoteCount { get; set; }
// Desire: inherited JsonIgnore attribute
public override IComparable SortValue => VoteCount;
}
更新:这是
System.Text.Json的预期行为。
:
链接到
这是众所周知的。属性不能继承System.Text.Json属性。属性需要放置在每个(反)可序列化覆盖上
作为一种解决方法,您可以使SortValue
成为一个公共的非虚拟代理,调用一些受保护的抽象属性,如:
public abstract class Base
{
protected abstract IComparable ProtectedSortValue { get; }
[JsonIgnore]
public IComparable SortValue => ProtectedSortValue;
}
public class Derived : Base
{
public int VoteCount { get; set; }
protected override IComparable ProtectedSortValue => VoteCount;
}
通过此更改,SortValue
将不会在派生类中序列化,而ProtectedSortValue
将根本不会序列化,因为只有公共属性被序列化。演示小提琴#3
(将[JsonIgnore]
添加到重写属性也会阻止其序列化,但是在每个派生类中都必须这样做,这似乎是您不想做的。)
原始答案:这可能是System.Text.Json
的一个限制,我可以使用以下代码重现您的问题:
var derived = new Derived { VoteCount = 101 };
var json1 = JsonSerializer.Serialize(derived, typeof(Derived));
Console.WriteLine(json1); // {"VoteCount":101,"SortValue":{}}
var json2 = JsonSerializer.Serialize(derived, typeof(Base));
Console.WriteLine(json2); //{}
当Derived
的实例序列化为类型Derived
时,将包括SortValue
属性;但是当序列化为typeBase
时,它不是。演示小提琴#1
但这种行为是故意的吗?和都不讨论是否继承了[JsonIgnore]
,但是,以及显示[AttributeUsage(AttributeTargets.Property,AllowMultiple=false)]
:
[AttributeUsage(AttributeTargets.Property,AllowMultiple=false)]
公共密封类JsonIgnoreAttribute:JsonAttribute
{
///
///初始化的新实例。
///
public JsonIgnoreAttribute(){}
}
请注意,AttributeUsageAttribute.Inherited
未设置。由于继承的的默认值如下所示:
true
如果属性可以由派生类和重写成员继承;否则,false
默认值为true
似乎[JsonIgnore]
应该被重写的属性继承。它肯定与Json.NET和DataContractJsonSerializer
不一致,后者分别尊重Newtonsoft.Json.JsonIgnoreAttribute
和IgnoreDataMemberAttribute
的继承,如demo fiddle 2所示。你可能想知道这件事;至少应该澄清文档。您是否设置了[AttributeUsage(Inherited=true)]
?请参阅“当属性声明为重写时,属性将丢失”-这是什么意思?澄清了这个问题--我的意思是派生实例不尊重它。我假设这意味着它没有被继承,因此“丢失”,所以您希望VoteCount
hidden?@DanielA.White-不,序列化时应该忽略SortValue。VoteCount是这里的序列化属性。非常好的信息,谢谢!要确认,可继承属性是否应该适用于抽象属性的派生重写?(在C#generally中)@NoahStahl-一般来说,应通过应用于属性来控制,该属性的默认值为true
。注释中的问题讨论了这一点。@NoahStahl-也就是说,使用反射只获取直接应用的属性是可能的,因此如果一个人正在编写大量使用反射的代码(序列化程序当然会这样做),那么如果他愿意,他可以避免使用该标准。我刚刚在repo中发现了这一点。看起来这是.NET团队的意图?在文档页面的下面有一节讨论了派生类型中的工作方式。似乎这就是这种行为的原因。
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public sealed class JsonIgnoreAttribute : JsonAttribute
{
/// <summary>
/// Initializes a new instance of <see cref="JsonIgnoreAttribute"/>.
/// </summary>
public JsonIgnoreAttribute() { }
}