Skip to content

Commit

Permalink
Fix binding logic for dictionaries with complex elements (#89117)
Browse files Browse the repository at this point in the history
* Fix binding logic for dictionaries with complex elements

* Remove interace impls not relevant to test and causing issues
  • Loading branch information
layomia committed Jul 19, 2023
1 parent 82f9a57 commit 5864743
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
""");
}

EmitBindCoreCall(elementType, $"{Identifier.element}!", Identifier.section, InitializationKind.None);
EmitBindCoreCall(elementType, Identifier.element, Identifier.section, InitializationKind.None);
_writer.WriteLine($"{objIdentifier}[{parsedKeyExpr}] = {Identifier.element};");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using Microsoft.Extensions.Configuration;
Expand Down Expand Up @@ -664,5 +666,35 @@ public struct StructWithParameterlessAndParameterizedCtor

public int MyInt { get; }
}

[TypeConverter(typeof(GeolocationTypeConverter))]
public struct Geolocation
{
public static readonly Geolocation Zero = new(0, 0);

public Geolocation(double latitude, double longitude)
{
Latitude = latitude;
Longitude = longitude;
}

public double Latitude { get; set; }

public double Longitude { get; set; }

private sealed class GeolocationTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) =>
throw new NotImplementedException();

public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) =>
throw new NotImplementedException();
}
}

public class GeolocationWrapper
{
public Geolocation Location { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1900,5 +1900,70 @@ public void AllowsCaseInsensitiveMatch()
GenericOptionsWithParamCtor<string> obj2 = configuration.Get<GenericOptionsWithParamCtor<string>>();
Assert.Equal("MyString", obj2.Value);
}

[Fact]
public void ObjWith_TypeConverter()
{
var configuration = TestHelpers.GetConfigurationFromJsonString("""
{
"Location":
{
"Latitude": 3,
"Longitude": 4,
}
}
""");

// TypeConverter impl is not honored (https://github.com/dotnet/runtime/issues/83599).

GeolocationWrapper obj = configuration.Get<GeolocationWrapper>();
ValidateGeolocation(obj.Location);

configuration = TestHelpers.GetConfigurationFromJsonString(""" { "Geolocation": "3, 4", } """);
obj = configuration.Get<GeolocationWrapper>();
Assert.Equal(Geolocation.Zero, obj.Location);
}

[Fact]
public void ComplexObj_As_Dictionary_Element()
{
var configuration = TestHelpers.GetConfigurationFromJsonString("""
{
"First":
{
"Latitude": 3,
"Longitude": 4,
}
}
""");

Geolocation obj = configuration.Get<IDictionary<string, Geolocation>>()["First"];
ValidateGeolocation(obj);

obj = configuration.Get<IReadOnlyDictionary<string, Geolocation>>()["First"];
ValidateGeolocation(obj);
}

[Fact]
public void ComplexObj_As_Enumerable_Element()
{
var configuration = TestHelpers.GetConfigurationFromJsonString("""{ "Enumerable": [{ "Latitude": 3, "Longitude": 4 }] }""")
.GetSection("Enumerable");

Geolocation obj = configuration.Get<IList<Geolocation>>()[0];
ValidateGeolocation(obj);

obj = configuration.Get<Geolocation[]>()[0];
ValidateGeolocation(obj);

obj = configuration.Get<IReadOnlyList<Geolocation>>()[0];
ValidateGeolocation(obj);
}

private void ValidateGeolocation(Geolocation location)
{
Assert.Equal(3, location.Latitude);
Assert.Equal(4, location.Longitude);
}
}
}

0 comments on commit 5864743

Please sign in to comment.