Skip to content

Commit ee67e2a

Browse files
committed
Cleanups
1 parent ebcd8f4 commit ee67e2a

12 files changed

+96
-80
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Microsoft.AspNetCore.Components.Endpoints.Binding;
5+
6+
internal sealed class NullableConverter<T> : FormDataConverter<T?> where T : struct
7+
{
8+
private readonly FormDataConverter<T> _nonNullableConverter;
9+
10+
public NullableConverter(FormDataConverter<T> nonNullableConverter)
11+
{
12+
_nonNullableConverter = nonNullableConverter;
13+
}
14+
15+
internal override bool TryRead(ref FormDataReader context, Type type, FormDataMapperOptions options, out T? result, out bool found)
16+
{
17+
if (!(_nonNullableConverter.TryRead(ref context, type, options, out var innerResult, out found) && found))
18+
{
19+
result = null;
20+
return false;
21+
}
22+
else
23+
{
24+
result = innerResult;
25+
return true;
26+
}
27+
}
28+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Microsoft.AspNetCore.Components.Endpoints.Binding;
5+
6+
internal sealed class ParsableConverter<T> : FormDataConverter<T>, ISingleValueConverter where T : IParsable<T>
7+
{
8+
internal override bool TryRead(ref FormDataReader reader, Type type, FormDataMapperOptions options, out T? result, out bool found)
9+
{
10+
found = reader.TryGetValue(out var value);
11+
if (found && T.TryParse(value, reader.Culture, out result))
12+
{
13+
return true;
14+
}
15+
else
16+
{
17+
result = default;
18+
return false;
19+
}
20+
}
21+
}

src/Components/Endpoints/src/Binding/DefaultFormValuesSupplier.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public bool CanBind(string formName, Type valueType)
3434
{
3535
return _formData.IsFormDataAvailable &&
3636
string.Equals(formName, _formData.Name, StringComparison.Ordinal) &&
37-
_options.HasConverter(valueType);
37+
_options.ResolveConverter(valueType) != null;
3838
}
3939

4040
public bool TryBind(string formName, Type valueType, [NotNullWhen(true)] out object? boundValue)

src/Components/Endpoints/src/Binding/NullableConverter.cs renamed to src/Components/Endpoints/src/Binding/Factories/NullableConverterFactory.cs

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,45 +7,26 @@ namespace Microsoft.AspNetCore.Components.Endpoints.Binding;
77

88
internal sealed class NullableConverterFactory : IFormDataConverterFactory
99
{
10-
public static bool CanConvert(Type type, FormDataMapperOptions options)
10+
public static readonly NullableConverterFactory Instance = new();
11+
12+
public bool CanConvert(Type type, FormDataMapperOptions options)
1113
{
1214
var underlyingType = Nullable.GetUnderlyingType(type);
13-
return underlyingType != null && options.HasConverter(underlyingType);
15+
return underlyingType != null && options.ResolveConverter(underlyingType) != null;
1416
}
1517

16-
public static FormDataConverter CreateConverter(Type type, FormDataMapperOptions options)
18+
public FormDataConverter CreateConverter(Type type, FormDataMapperOptions options)
1719
{
1820
var underlyingType = Nullable.GetUnderlyingType(type);
1921
Debug.Assert(underlyingType != null);
22+
2023
var underlyingConverter = options.ResolveConverter(underlyingType);
2124
Debug.Assert(underlyingConverter != null);
25+
2226
var expectedConverterType = typeof(NullableConverter<>).MakeGenericType(underlyingType);
2327
Debug.Assert(expectedConverterType != null);
28+
2429
return Activator.CreateInstance(expectedConverterType, underlyingConverter) as FormDataConverter ??
2530
throw new InvalidOperationException($"Unable to create converter for type '{type}'.");
2631
}
2732
}
28-
29-
internal class NullableConverter<T> : FormDataConverter<T?> where T : struct
30-
{
31-
private readonly FormDataConverter<T> _nonNullableConverter;
32-
33-
public NullableConverter(FormDataConverter<T> nonNullableConverter)
34-
{
35-
_nonNullableConverter = nonNullableConverter;
36-
}
37-
38-
internal override bool TryRead(ref FormDataReader context, Type type, FormDataMapperOptions options, out T? result, out bool found)
39-
{
40-
if (!(_nonNullableConverter.TryRead(ref context, type, options, out var innerResult, out found) && found))
41-
{
42-
result = null;
43-
return false;
44-
}
45-
else
46-
{
47-
result = innerResult;
48-
return true;
49-
}
50-
}
51-
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using Microsoft.Extensions.Internal;
5+
6+
namespace Microsoft.AspNetCore.Components.Endpoints.Binding;
7+
8+
internal sealed class ParsableConverterFactory : IFormDataConverterFactory
9+
{
10+
public static readonly ParsableConverterFactory Instance = new();
11+
12+
public bool CanConvert(Type type, FormDataMapperOptions options)
13+
{
14+
return ClosedGenericMatcher.ExtractGenericInterface(type, typeof(IParsable<>)) is not null;
15+
}
16+
17+
public FormDataConverter CreateConverter(Type type, FormDataMapperOptions options)
18+
{
19+
return Activator.CreateInstance(typeof(ParsableConverter<>).MakeGenericType(type)) as FormDataConverter ??
20+
throw new InvalidOperationException($"Unable to create converter for '{type.FullName}'.");
21+
}
22+
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
1+
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
namespace Microsoft.AspNetCore.Components.Endpoints.Binding;
55

6+
// Base type for all types that can map from form data to a .NET type.
67
internal class FormDataConverter
78
{
89
}

src/Components/Endpoints/src/Binding/FormDataMapperOptions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ public FormDataMapperOptions()
1414
{
1515
_converters = new(WellKnownConverters.Converters);
1616

17-
_factories.Add((type, options) => ParsableConverterFactory.CanConvert(type, options) ? ParsableConverterFactory.CreateConverter(type, options) : null);
18-
_factories.Add((type, options) => NullableConverterFactory.CanConvert(type, options) ? NullableConverterFactory.CreateConverter(type, options) : null);
17+
_factories.Add((type, options) => ParsableConverterFactory.Instance.CanConvert(type, options) ? ParsableConverterFactory.Instance.CreateConverter(type, options) : null);
18+
_factories.Add((type, options) => NullableConverterFactory.Instance.CanConvert(type, options) ? NullableConverterFactory.Instance.CreateConverter(type, options) : null);
1919
}
2020

2121
internal bool HasConverter(Type valueType) => _converters.ContainsKey(valueType);
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
1+
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
namespace Microsoft.AspNetCore.Components.Endpoints.Binding;
55

66
internal interface IFormDataConverterFactory
77
{
8-
public static abstract bool CanConvert(Type type, FormDataMapperOptions options);
8+
public bool CanConvert(Type type, FormDataMapperOptions options);
99

10-
public static abstract FormDataConverter CreateConverter(Type type, FormDataMapperOptions options);
10+
public FormDataConverter CreateConverter(Type type, FormDataMapperOptions options);
1111
}

src/Components/Endpoints/src/Binding/ParsableConverter.cs

Lines changed: 0 additions & 39 deletions
This file was deleted.

src/Components/Endpoints/src/Microsoft.AspNetCore.Components.Endpoints.csproj

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,14 @@
3232
<Compile Include="$(RepoRoot)src\Shared\Components\ComponentParameter.cs" LinkBase="DependencyInjection" />
3333
<Compile Include="$(RepoRoot)src\Shared\Components\PrerenderComponentApplicationStore.cs" LinkBase="DependencyInjection" />
3434
<Compile Include="$(RepoRoot)src\Shared\Components\ProtectedPrerenderComponentApplicationStore.cs" LinkBase="DependencyInjection" />
35+
<Compile Include="$(RepoRoot)src\Shared\ClosedGenericMatcher\ClosedGenericMatcher.cs" LinkBase="Binding" />
3536
<Compile Include="$(ComponentsSharedSourceRoot)src\CacheHeaderSettings.cs" Link="Shared\CacheHeaderSettings.cs" />
3637

3738
<Compile Include="$(SharedSourceRoot)PropertyHelper\**\*.cs" />
3839

3940
<!-- Add a project dependency without reference output assemblies to enforce build order -->
4041
<!-- Applying workaround for https://github.com/microsoft/msbuild/issues/2661 and https://github.com/dotnet/sdk/issues/952 -->
41-
<ProjectReference Include="..\..\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj"
42-
Condition="'$(BuildNodeJS)' != 'false' and '$(BuildingInsideVisualStudio)' != 'true'"
43-
Private="false"
44-
ReferenceOutputAssembly="false"
45-
SkipGetTargetFrameworkProperties="true"
46-
UndefineProperties="TargetFramework" />
42+
<ProjectReference Include="..\..\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj" Condition="'$(BuildNodeJS)' != 'false' and '$(BuildingInsideVisualStudio)' != 'true'" Private="false" ReferenceOutputAssembly="false" SkipGetTargetFrameworkProperties="true" UndefineProperties="TargetFramework" />
4743
</ItemGroup>
4844

4945
<ItemGroup>

src/Components/Endpoints/test/Binding/FormDataMapperTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public void CanDeserialize_CustomParsableTypes()
7676
// Assert
7777
Assert.Equal(expected, result);
7878
}
79-
79+
8080
#nullable enable
8181
[Fact]
8282
public void CanDeserialize_NullableCustomParsableTypes()
@@ -299,6 +299,7 @@ public static bool TryParse([NotNullWhen(true)] string s, IFormatProvider provid
299299
internal struct ValuePoint : IParsable<ValuePoint>, IEquatable<ValuePoint>
300300
{
301301
public int X { get; set; }
302+
302303
public int Y { get; set; }
303304

304305
public static ValuePoint Parse(string s, IFormatProvider provider)

src/Shared/ClosedGenericMatcher/ClosedGenericMatcher.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,13 @@ internal static class ClosedGenericMatcher
3232
/// </remarks>
3333
public static Type? ExtractGenericInterface(Type queryType, Type interfaceType)
3434
{
35+
#if !NET8_0_OR_GREATER
3536
ArgumentNullThrowHelper.ThrowIfNull(queryType);
3637
ArgumentNullThrowHelper.ThrowIfNull(interfaceType);
38+
#else
39+
ArgumentNullException.ThrowIfNull(queryType);
40+
ArgumentNullException.ThrowIfNull(interfaceType);
41+
#endif
3742

3843
if (IsGenericInstantiation(queryType, interfaceType))
3944
{

0 commit comments

Comments
 (0)