【问题标题】:C# - Overridden protected method in inheriting class not calledC# - 在未调用的继承类中被覆盖的受保护方法
【发布时间】: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


【解决方案1】:

AbstractContractResolverFromFile

protected new virtual string ResolvePropertyName

protected override string ResolvePropertyName

新的东西隐藏了继承的实现,我通常建议避免它。这是需要注意的事情,因为您可能会在代码中遇到它。

【讨论】:

  • 对不起,Ben,但我认为我不能同时使用 overridevirtual 一个函数。 AbstractContractResolver 继承自 Newtonsoft 的 DefaultContractResolver
  • 是的,抱歉应该是protected override string ResolvePropertyName我会更新我的答案
  • 此解决方案仍在使用virtual override,这是不可能的,除非它使用最新的 C# 版本(和 Visual Studio)编译器。在 VS Code 上使用 C# 的 Dotnet Core 5(自上周以来的最新版本)至少不允许同时覆盖和虚拟化。
  • 对不起,我真的搞砸了我的答案,现在应该是这样,只需将新的虚拟更改为覆盖。
  • 谢谢@Ben,我在发布这个问题之前就试过了。我决定放弃对DefaultContractResolver 的覆盖,只是创建了一个扩展方法,根据继承类型(FromFileAbstractContractResolver 解析器)执行我想做的事情。已经可以工作了 - newing / virtualizing 的行为很奇怪(至少在我尝试的两个继承级别方面)。
猜你喜欢
  • 2020-09-09
  • 2015-10-07
  • 2015-10-01
  • 2010-09-14
  • 2013-07-01
  • 2022-07-08
  • 2014-06-29
  • 1970-01-01
  • 2011-08-04
相关资源
最近更新 更多