【发布时间】:2020-11-16 11:51:08
【问题描述】:
这是一个与 C# 对象继承有关的问题,但在 受保护方法 Newtonsoft.Json.Serialization.DefaultContractResolver
的上下文中我遵循了这篇关于如何使用映射属性使用 Newtonsoft 库进行序列化的建议。 DefaultContractResolver usage
我创建了类 AbstractContractResolver、AbstractContractResolverFromFile、CustomClassImplementedContractResolver (此处为示例目的自定义命名)
public abstract class AbstractContractResolver : DefaultContractResolver{
protected Dictionary<string, string> PropertyMappings {get { return this.getPropertyMappings(); }}
protected override string ResolvePropertyName(string propertyName)
{
string resolvedName = null;
var resolved = this.getPropertyMappings().TryGetValue(propertyName, out resolvedName);
return (resolved) ? propertyName : base.ResolvePropertyName(propertyName);
}
}
public abstract class AbstractContractResolverFromFile : AbstractContractResolver{
public AbstractContractResolverFromFile(string mapperFileName){
if(string.IsNullOrEmpty(mapperFileName)){
throw new InvalidOperationException(string.Format("The abstract class {0} uses a mapper file as input to resolve and populate properties. Please specify a valid mapper file!", this.GetType()));
}
this.MapperFileName = mapperFileName;
}
protected new virtual string ResolvePropertyName(string propertyName)
{
string field = propertyName;
if(this.PropertyMappings.Any() && this.PropertyMappings.ContainsKey(propertyName)){
field = this.PropertyMappings[propertyName];
}
else{
field = base.ResolvePropertyName(propertyName);
}
return field;
}
public class CustomClassImplementedContractResolver : AbstractContractResolverFromFile{
public CustomClassImplementedContractResolver (string mapperFileName) : base(mapperFileName){
}
protected override string ResolvePropertyName(string propertyName)
{
return base.ResolvePropertyName(propertyName);
}
CustomClassImplementedContractResolver 继承 AbstractContractResolverFromFile 继承自另一个类,依此类推。
我是这样使用的:
string mapperfile = "filepath/to/file.json";
CustomClassImplementedContractResolver contractResolver = new CustomClassImplementedContractResolver(mapperfile);
// Custom implementation to store mappings (PropertyName, FieldSource) in a Dictionary<string, string>
await contractResolver.PopulatePropertyMappings();
// Reading JSON and deserializing
using(TextReader tr = new StreamReader(jsonfile)){
string jsoncontent = await tr.ReadToEndAsync();
try{
var settings = new JsonSerializerSettings();
// Set the ContractResolver
settings.ContractResolver = contractResolver;
var item = JsonConvert.DeserializeObject<CustomClass>(jsoncontent, settings);
问题 -
请查看我在上述所有这些类中的受保护函数
ResolvePropertyName的实现,并帮助我找到问题。
我认为我错误地覆盖了 - 并且 newing 正在进一步覆盖的方法...
由于调用了不正确的ResolvePropertyName,因此无法获取(从文件中)创建的自定义映射...
-
DeserializeObject执行时,代码内部调用了
ResolvePropertyName,但是当前的contractResolver并没有调用被覆盖的方法,它实际上调用了第一个基址AbstractContractResolver.ResolvePropertyName。 换句话说,我在所有 4 个函数(包括CustomClassImplementedContractResolver.ResolvePropertyName)中都设置了断点,但它只执行AbstractContractResolver函数。 -
奇怪的是:我使用 Visual Studio Code 并在
base.ResolvePropertyName上按 F12 可以正确导航(正如我所期望的那样)从每个继承的函数直到 base。
【问题讨论】:
-
你的意思是
virtual new string ResolvePropertyName吗?在继承类中我是否继续在所有相互继承的子类中这样做? -
不,不要使用
new。 -
当类 AbstractSomething 不是抽象类时不要调用它。
-
感谢您发现这一点。我将更新基类并使其抽象。 @Geert,你能给我举个例子来说明你的意思吗?
-
按照 Ben 的回答中提到的去做。并做一些研究以找出
new的真正含义。
标签: c# inheritance json.net overriding