Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实现抽象基字段时在序列化期间继承属性_C#_.net_System.text.json - Fatal编程技术网

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
属性;但是当序列化为type
Base
时,它不是。演示小提琴#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() { }
}