2

So, I am new to Yaml and YamlDotNet. I wrote the following code to parse a yaml file I am using for configuration of an client API...

public bool TryGet(string path, out DiagnosticScannerConfig config)
{
    var deserializer = new DeserializerBuilder()
        .WithNamingConvention(new HyphenatedNamingConvention())
        .Build();

    try
    {
        using (var reader = File.OpenText(path))
        {
            var deserializedConfig = deserializer.Deserialize<InternalDiagnosticScannerConfig>(reader);

            config = new DiagnosticScannerConfigImpl(deserializedConfig);
            return true;
        }
    }
    catch (Exception e)
    {
        config = DiagnosticAnalyzerConfigCache.Default;
        return true;
    }
}

public interface DiagnosticScannerConfig
{
    DiagnosticAnalyzerConfig Analyzer { get; }
}

public interface DiagnosticAnalyzerConfig
{
    uint HighClosureRateWarningThreshold { get; }
    uint HighCreationRateWarningThreshold { get; }
    uint QueueHighFlowThreshold { get; }
    uint QueueLowFlowThreshold { get; }
    decimal MessageRedeliveryCoefficient { get; }
    decimal SocketUsageCoefficient { get; }
    decimal RuntimeProcessUsageCoefficient { get; }
    decimal FileDescriptorUsageWarningCoefficient { get; }
    decimal ConsumerUtilizationWarningCoefficient { get; }
}

class DiagnosticScannerConfigImpl : DiagnosticScannerConfig
{
    public DiagnosticScannerConfigImpl(InternalDiagnosticScannerConfig config)
    {
        Analyzer = new DiagnosticAnalyzerConfigImpl(config.Analyzer);
    }

    class DiagnosticAnalyzerConfigImpl : DiagnosticAnalyzerConfig
    {
        public DiagnosticAnalyzerConfigImpl(Analyzer config)
        {
            HighClosureRateWarningThreshold = config.HighClosureRateWarningThreshold;
            HighCreationRateWarningThreshold = config.HighCreationRateWarningThreshold;
            QueueHighFlowThreshold = config.QueueHighFlowThreshold;
            QueueLowFlowThreshold = config.QueueLowFlowThreshold;
            MessageRedeliveryCoefficient = config.MessageRedeliveryCoefficient;
            SocketUsageCoefficient = config.SocketUsageCoefficient;
            RuntimeProcessUsageCoefficient = config.RuntimeProcessUsageCoefficient;
            FileDescriptorUsageWarningCoefficient = config.FileDescriptorUsageWarningCoefficient;
            ConsumerUtilizationWarningCoefficient = config.ConsumerUtilizationWarningCoefficient;
        }

        public uint HighClosureRateWarningThreshold { get; }
        public uint HighCreationRateWarningThreshold { get; }
        public uint QueueHighFlowThreshold { get; }
        public uint QueueLowFlowThreshold { get; }
        public decimal MessageRedeliveryCoefficient { get; }
        public decimal SocketUsageCoefficient { get; }
        public decimal RuntimeProcessUsageCoefficient { get; }
        public decimal FileDescriptorUsageWarningCoefficient { get; }
        public decimal ConsumerUtilizationWarningCoefficient { get; }
    }

    public DiagnosticAnalyzerConfig Analyzer { get; }
}


public class Analyzer
{
    [YamlMember(Alias = "high-closure-rate-warning-threshold")]
    public uint HighClosureRateWarningThreshold { get; set; }

    [YamlMember(Alias = "high-creation-rate-warning-threshold")]
    public uint HighCreationRateWarningThreshold { get; set; }

    [YamlMember(Alias = "queue-high-flow-threshold")]
    public uint QueueHighFlowThreshold { get; set; }

    [YamlMember(Alias = "queue-low-flow-threshold")]
    public uint QueueLowFlowThreshold { get; set; }

    [YamlMember(Alias = "message-redelivery-coefficient")]
    public decimal MessageRedeliveryCoefficient { get; set; }

    [YamlMember(Alias = "socket-usage-coefficient")]
    public decimal SocketUsageCoefficient { get; set; }

    [YamlMember(Alias = "runtime-process-usage-coefficient")]
    public decimal RuntimeProcessUsageCoefficient { get; set; }

    [YamlMember(Alias = "file-descriptor-usage-warning-coefficient")]
    public decimal FileDescriptorUsageWarningCoefficient { get; set; }

    [YamlMember(Alias = "consumer-utilization-warning-coefficient")]
    public decimal ConsumerUtilizationWarningCoefficient { get; set; }
}

public class InternalDiagnosticScannerConfig
{
    public Analyzer Analyzer { get; }
}

I trying to parse the following yaml file:

---
    high-closure-rate-warning-threshold:  90
    high-creation-rate-warning-threshold: 60
    queue-high-flow-threshold:  90
    queue-low-flow-threshold: 10
    message-redelivery-coefficient: 0.60
    socket-usage-coefficient: 0.60
    runtime-process-usage-coefficient:  0.65
    file-descriptor-usage-warning-coefficient:  0.65
    consumer-utilization-warning-coefficient: 0.65
...

When I execute the above code I am getting the following error:

YamlDotNet.Core.YamlException: (Line: 2, Col: 5, Idx: 8) - (Line: 2, Col: 5, Idx: 8): Exception during deserialization ---> System.Runtime.Serialization.SerializationException: Property 'high-closure-rate-warning-threshold' not found on type 'HareDu.Diagnostics.Configuration.InternalDiagnosticScannerConfig'. at YamlDotNet.Serialization.TypeInspectors.TypeInspectorSkeleton.GetProperty(Type type, Object container, String name, Boolean ignoreUnmatched) at YamlDotNet.Serialization.NodeDeserializers.ObjectNodeDeserializer.YamlDotNet.Serialization.INodeDeserializer.Deserialize(IParser parser, Type expectedType, Func`3 nestedObjectDeserializer, Object& value) at YamlDotNet.Serialization.ValueDeserializers.NodeValueDeserializer.DeserializeValue(IParser parser, Type expectedType, SerializerState state, IValueDeserializer nestedObjectDeserializer) --- End of inner exception stack trace --- at YamlDotNet.Serialization.ValueDeserializers.NodeValueDeserializer.DeserializeValue(IParser parser, Type expectedType, SerializerState state, IValueDeserializer nestedObjectDeserializer) at YamlDotNet.Serialization.ValueDeserializers.AliasValueDeserializer.DeserializeValue(IParser parser, Type expectedType, SerializerState state, IValueDeserializer nestedObjectDeserializer) at YamlDotNet.Serialization.Deserializer.Deserialize(IParser parser, Type type) at YamlDotNet.Serialization.Deserializer.Deserialize[T](IParser parser) at YamlDotNet.Serialization.Deserializer.Deserialize[T](TextReader input) at HareDu.Diagnostics.Configuration.DiagnosticScannerConfigProvider.TryGet(String path, DiagnosticScannerConfig& config) in /Users/albert/Documents/Git/HareDu2/src/HareDu.Diagnostics/Configuration/DiagnosticScannerConfigProvider.cs:line 59

Albert
  • 33
  • 6

1 Answers1

1

The exception message is telling you the problem: your type InternalDiagnosticScannerConfig does not have a 'high-closure-rate-warning-threshold' property. Indeed on your code that property is defined in the Analyzer class. You should either deserialize to that type, or update your YAML so that it's structure reflects your classes.

In practice, either use this:

deserializer.Deserialize<InternalDiagnosticScannerConfig>(reader);

Or this:

---
analyzer:
    high-closure-rate-warning-threshold:  90
    high-creation-rate-warning-threshold: 60
    queue-high-flow-threshold:  90
    queue-low-flow-threshold: 10
    message-redelivery-coefficient: 0.60
    socket-usage-coefficient: 0.60
    runtime-process-usage-coefficient:  0.65
    file-descriptor-usage-warning-coefficient:  0.65
    consumer-utilization-warning-coefficient: 0.65
...
Antoine Aubry
  • 12,203
  • 10
  • 45
  • 74
  • This worked perfectly. Since then I've made more advanced changes to the YAML file but this made me confident to take it to the next. Thank you so much for getting me over this hump. – Albert Dec 27 '19 at 15:25