Add support for passing CultureInfo to binders

This change allows the binding infrastructure to accept a CultureInfo
everywhere we create a binder. The next step will be to add support to
the binding directive attribute to pass a culture.
This commit is contained in:
Ryan Nowak 2019-06-25 21:31:09 -07:00 committed by Ryan Nowak
parent b2023bbbf1
commit 8d41acba67
3 changed files with 162 additions and 87 deletions

View File

@ -148,23 +148,23 @@ namespace Microsoft.AspNetCore.Components
} }
public static partial class EventCallbackFactoryBinderExtensions public static partial class EventCallbackFactoryBinderExtensions
{ {
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<bool> setter, bool existingValue) { throw null; } public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<bool> setter, bool existingValue, System.Globalization.CultureInfo culture = null) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<System.DateTime> setter, System.DateTime existingValue) { throw null; } public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<System.DateTime> setter, System.DateTime existingValue, System.Globalization.CultureInfo culture = null) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<System.DateTime> setter, System.DateTime existingValue, string format) { throw null; } public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<System.DateTime> setter, System.DateTime existingValue, string format, System.Globalization.CultureInfo culture = null) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<decimal> setter, decimal existingValue) { throw null; } public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<decimal> setter, decimal existingValue, System.Globalization.CultureInfo culture = null) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<double> setter, double existingValue) { throw null; } public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<double> setter, double existingValue, System.Globalization.CultureInfo culture = null) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<int> setter, int existingValue) { throw null; } public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<int> setter, int existingValue, System.Globalization.CultureInfo culture = null) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<long> setter, long existingValue) { throw null; } public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<long> setter, long existingValue, System.Globalization.CultureInfo culture = null) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<bool?> setter, bool? existingValue) { throw null; } public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<bool?> setter, bool? existingValue, System.Globalization.CultureInfo culture = null) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<System.DateTime?> setter, System.DateTime? existingValue) { throw null; } public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<System.DateTime?> setter, System.DateTime? existingValue, System.Globalization.CultureInfo culture = null) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<decimal?> setter, decimal? existingValue) { throw null; } public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<decimal?> setter, decimal? existingValue, System.Globalization.CultureInfo culture = null) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<double?> setter, double? existingValue) { throw null; } public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<double?> setter, double? existingValue, System.Globalization.CultureInfo culture = null) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<int?> setter, int? existingValue) { throw null; } public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<int?> setter, int? existingValue, System.Globalization.CultureInfo culture = null) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<long?> setter, long? existingValue) { throw null; } public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<long?> setter, long? existingValue, System.Globalization.CultureInfo culture = null) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<float?> setter, float? existingValue) { throw null; } public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<float?> setter, float? existingValue, System.Globalization.CultureInfo culture = null) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<float> setter, float existingValue) { throw null; } public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<float> setter, float existingValue, System.Globalization.CultureInfo culture = null) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<string> setter, string existingValue) { throw null; } public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<string> setter, string existingValue, System.Globalization.CultureInfo culture = null) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder<T>(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<T> setter, T existingValue) { throw null; } public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder<T>(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<T> setter, T existingValue, System.Globalization.CultureInfo culture = null) { throw null; }
} }
public static partial class EventCallbackFactoryUIEventArgsExtensions public static partial class EventCallbackFactoryUIEventArgsExtensions
{ {

View File

@ -25,13 +25,13 @@ namespace Microsoft.AspNetCore.Components
// For now we're not necessarily handling this correctly since we parse the same way for number and text. // For now we're not necessarily handling this correctly since we parse the same way for number and text.
public static class EventCallbackFactoryBinderExtensions public static class EventCallbackFactoryBinderExtensions
{ {
private delegate bool BindConverter<T>(object obj, out T value); private delegate bool BindConverter<T>(object obj, CultureInfo culture, out T value);
// Perf: conversion delegates are written as static funcs so we can prevent // Perf: conversion delegates are written as static funcs so we can prevent
// allocations for these simple cases. // allocations for these simple cases.
private readonly static BindConverter<string> ConvertToString = ConvertToStringCore; private readonly static BindConverter<string> ConvertToString = ConvertToStringCore;
private static bool ConvertToStringCore(object obj, out string value) private static bool ConvertToStringCore(object obj, CultureInfo culture, out string value)
{ {
// We expect the input to already be a string. // We expect the input to already be a string.
value = (string)obj; value = (string)obj;
@ -41,14 +41,14 @@ namespace Microsoft.AspNetCore.Components
private static BindConverter<bool> ConvertToBool = ConvertToBoolCore; private static BindConverter<bool> ConvertToBool = ConvertToBoolCore;
private static BindConverter<bool?> ConvertToNullableBool = ConvertToNullableBoolCore; private static BindConverter<bool?> ConvertToNullableBool = ConvertToNullableBoolCore;
private static bool ConvertToBoolCore(object obj, out bool value) private static bool ConvertToBoolCore(object obj, CultureInfo culture, out bool value)
{ {
// We expect the input to already be a bool. // We expect the input to already be a bool.
value = (bool)obj; value = (bool)obj;
return true; return true;
} }
private static bool ConvertToNullableBoolCore(object obj, out bool? value) private static bool ConvertToNullableBoolCore(object obj, CultureInfo culture, out bool? value)
{ {
// We expect the input to already be a bool. // We expect the input to already be a bool.
value = (bool?)obj; value = (bool?)obj;
@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.Components
private static BindConverter<int> ConvertToInt = ConvertToIntCore; private static BindConverter<int> ConvertToInt = ConvertToIntCore;
private static BindConverter<int?> ConvertToNullableInt = ConvertToNullableIntCore; private static BindConverter<int?> ConvertToNullableInt = ConvertToNullableIntCore;
private static bool ConvertToIntCore(object obj, out int value) private static bool ConvertToIntCore(object obj, CultureInfo culture, out int value)
{ {
var text = (string)obj; var text = (string)obj;
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.Components
return false; return false;
} }
if (!int.TryParse(text, NumberStyles.Integer, CultureInfo.CurrentCulture, out var converted)) if (!int.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted))
{ {
value = default; value = default;
return false; return false;
@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.Components
return true; return true;
} }
private static bool ConvertToNullableIntCore(object obj, out int? value) private static bool ConvertToNullableIntCore(object obj, CultureInfo culture, out int? value)
{ {
var text = (string)obj; var text = (string)obj;
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
@ -86,7 +86,7 @@ namespace Microsoft.AspNetCore.Components
return true; return true;
} }
if (!int.TryParse(text, NumberStyles.Integer, CultureInfo.CurrentCulture, out var converted)) if (!int.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted))
{ {
value = default; value = default;
return false; return false;
@ -99,7 +99,7 @@ namespace Microsoft.AspNetCore.Components
private static BindConverter<long> ConvertToLong = ConvertToLongCore; private static BindConverter<long> ConvertToLong = ConvertToLongCore;
private static BindConverter<long?> ConvertToNullableLong = ConvertToNullableLongCore; private static BindConverter<long?> ConvertToNullableLong = ConvertToNullableLongCore;
private static bool ConvertToLongCore(object obj, out long value) private static bool ConvertToLongCore(object obj, CultureInfo culture, out long value)
{ {
var text = (string)obj; var text = (string)obj;
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
@ -108,7 +108,7 @@ namespace Microsoft.AspNetCore.Components
return false; return false;
} }
if (!long.TryParse(text, NumberStyles.Integer, CultureInfo.CurrentCulture, out var converted)) if (!long.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted))
{ {
value = default; value = default;
return false; return false;
@ -118,7 +118,7 @@ namespace Microsoft.AspNetCore.Components
return true; return true;
} }
private static bool ConvertToNullableLongCore(object obj, out long? value) private static bool ConvertToNullableLongCore(object obj, CultureInfo culture, out long? value)
{ {
var text = (string)obj; var text = (string)obj;
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
@ -127,7 +127,7 @@ namespace Microsoft.AspNetCore.Components
return true; return true;
} }
if (!long.TryParse(text, NumberStyles.Integer, CultureInfo.CurrentCulture, out var converted)) if (!long.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted))
{ {
value = default; value = default;
return false; return false;
@ -140,7 +140,7 @@ namespace Microsoft.AspNetCore.Components
private static BindConverter<float> ConvertToFloat = ConvertToFloatCore; private static BindConverter<float> ConvertToFloat = ConvertToFloatCore;
private static BindConverter<float?> ConvertToNullableFloat = ConvertToNullableFloatCore; private static BindConverter<float?> ConvertToNullableFloat = ConvertToNullableFloatCore;
private static bool ConvertToFloatCore(object obj, out float value) private static bool ConvertToFloatCore(object obj, CultureInfo culture, out float value)
{ {
var text = (string)obj; var text = (string)obj;
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
@ -149,7 +149,7 @@ namespace Microsoft.AspNetCore.Components
return false; return false;
} }
if (!float.TryParse(text, NumberStyles.Number, CultureInfo.CurrentCulture, out var converted)) if (!float.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted))
{ {
value = default; value = default;
return false; return false;
@ -159,7 +159,7 @@ namespace Microsoft.AspNetCore.Components
return true; return true;
} }
private static bool ConvertToNullableFloatCore(object obj, out float? value) private static bool ConvertToNullableFloatCore(object obj, CultureInfo culture, out float? value)
{ {
var text = (string)obj; var text = (string)obj;
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
@ -168,7 +168,7 @@ namespace Microsoft.AspNetCore.Components
return true; return true;
} }
if (!float.TryParse(text, NumberStyles.Number, CultureInfo.CurrentCulture, out var converted)) if (!float.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted))
{ {
value = default; value = default;
return false; return false;
@ -181,7 +181,7 @@ namespace Microsoft.AspNetCore.Components
private static BindConverter<double> ConvertToDouble = ConvertToDoubleCore; private static BindConverter<double> ConvertToDouble = ConvertToDoubleCore;
private static BindConverter<double?> ConvertToNullableDouble = ConvertToNullableDoubleCore; private static BindConverter<double?> ConvertToNullableDouble = ConvertToNullableDoubleCore;
private static bool ConvertToDoubleCore(object obj, out double value) private static bool ConvertToDoubleCore(object obj, CultureInfo culture, out double value)
{ {
var text = (string)obj; var text = (string)obj;
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
@ -190,7 +190,7 @@ namespace Microsoft.AspNetCore.Components
return false; return false;
} }
if (!double.TryParse(text, NumberStyles.Number, CultureInfo.CurrentCulture, out var converted)) if (!double.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted))
{ {
value = default; value = default;
return false; return false;
@ -200,7 +200,7 @@ namespace Microsoft.AspNetCore.Components
return true; return true;
} }
private static bool ConvertToNullableDoubleCore(object obj, out double? value) private static bool ConvertToNullableDoubleCore(object obj, CultureInfo culture, out double? value)
{ {
var text = (string)obj; var text = (string)obj;
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
@ -209,7 +209,7 @@ namespace Microsoft.AspNetCore.Components
return true; return true;
} }
if (!double.TryParse(text, NumberStyles.Number, CultureInfo.CurrentCulture, out var converted)) if (!double.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted))
{ {
value = default; value = default;
return false; return false;
@ -222,7 +222,7 @@ namespace Microsoft.AspNetCore.Components
private static BindConverter<decimal> ConvertToDecimal = ConvertToDecimalCore; private static BindConverter<decimal> ConvertToDecimal = ConvertToDecimalCore;
private static BindConverter<decimal?> ConvertToNullableDecimal = ConvertToNullableDecimalCore; private static BindConverter<decimal?> ConvertToNullableDecimal = ConvertToNullableDecimalCore;
private static bool ConvertToDecimalCore(object obj, out decimal value) private static bool ConvertToDecimalCore(object obj, CultureInfo culture, out decimal value)
{ {
var text = (string)obj; var text = (string)obj;
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
@ -231,7 +231,7 @@ namespace Microsoft.AspNetCore.Components
return false; return false;
} }
if (!decimal.TryParse(text, NumberStyles.Number, CultureInfo.CurrentCulture, out var converted)) if (!decimal.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted))
{ {
value = default; value = default;
return false; return false;
@ -241,7 +241,7 @@ namespace Microsoft.AspNetCore.Components
return true; return true;
} }
private static bool ConvertToNullableDecimalCore(object obj, out decimal? value) private static bool ConvertToNullableDecimalCore(object obj, CultureInfo culture, out decimal? value)
{ {
var text = (string)obj; var text = (string)obj;
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
@ -250,7 +250,7 @@ namespace Microsoft.AspNetCore.Components
return true; return true;
} }
if (!decimal.TryParse(text, NumberStyles.Number, CultureInfo.CurrentCulture, out var converted)) if (!decimal.TryParse(text, NumberStyles.Number, culture ?? CultureInfo.CurrentCulture, out var converted))
{ {
value = default; value = default;
return false; return false;
@ -263,7 +263,7 @@ namespace Microsoft.AspNetCore.Components
private static BindConverter<DateTime> ConvertToDateTime = ConvertToDateTimeCore; private static BindConverter<DateTime> ConvertToDateTime = ConvertToDateTimeCore;
private static BindConverter<DateTime?> ConvertToNullableDateTime = ConvertToNullableDateTimeCore; private static BindConverter<DateTime?> ConvertToNullableDateTime = ConvertToNullableDateTimeCore;
private static bool ConvertToDateTimeCore(object obj, out DateTime value) private static bool ConvertToDateTimeCore(object obj, CultureInfo culture, out DateTime value)
{ {
var text = (string)obj; var text = (string)obj;
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
@ -272,7 +272,7 @@ namespace Microsoft.AspNetCore.Components
return false; return false;
} }
if (!DateTime.TryParse(text, CultureInfo.CurrentCulture, DateTimeStyles.None, out var converted)) if (!DateTime.TryParse(text, culture ?? CultureInfo.CurrentCulture, DateTimeStyles.None, out var converted))
{ {
value = default; value = default;
return false; return false;
@ -282,7 +282,7 @@ namespace Microsoft.AspNetCore.Components
return true; return true;
} }
private static bool ConvertToNullableDateTimeCore(object obj, out DateTime? value) private static bool ConvertToNullableDateTimeCore(object obj, CultureInfo culture, out DateTime? value)
{ {
var text = (string)obj; var text = (string)obj;
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
@ -291,7 +291,7 @@ namespace Microsoft.AspNetCore.Components
return true; return true;
} }
if (!DateTime.TryParse(text, CultureInfo.CurrentCulture, DateTimeStyles.None, out var converted)) if (!DateTime.TryParse(text, culture ?? CultureInfo.CurrentCulture, DateTimeStyles.None, out var converted))
{ {
value = default; value = default;
return false; return false;
@ -301,7 +301,7 @@ namespace Microsoft.AspNetCore.Components
return true; return true;
} }
private static bool ConvertToEnum<T>(object obj, out T value) where T : struct, Enum private static bool ConvertToEnum<T>(object obj, CultureInfo culture, out T value) where T : struct, Enum
{ {
var text = (string)obj; var text = (string)obj;
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
@ -320,7 +320,7 @@ namespace Microsoft.AspNetCore.Components
return true; return true;
} }
private static bool ConvertToNullableEnum<T>(object obj, out Nullable<T> value) where T : struct, Enum private static bool ConvertToNullableEnum<T>(object obj, CultureInfo culture, out T? value) where T : struct, Enum
{ {
var text = (string)obj; var text = (string)obj;
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
@ -346,14 +346,16 @@ namespace Microsoft.AspNetCore.Components
/// <param name="receiver"></param> /// <param name="receiver"></param>
/// <param name="setter"></param> /// <param name="setter"></param>
/// <param name="existingValue"></param> /// <param name="existingValue"></param>
/// <param name="culture"></param>
/// <returns></returns> /// <returns></returns>
public static EventCallback<UIChangeEventArgs> CreateBinder( public static EventCallback<UIChangeEventArgs> CreateBinder(
this EventCallbackFactory factory, this EventCallbackFactory factory,
object receiver, object receiver,
Action<string> setter, Action<string> setter,
string existingValue) string existingValue,
CultureInfo culture = null)
{ {
return CreateBinderCore<string>(factory, receiver, setter, ConvertToString); return CreateBinderCore<string>(factory, receiver, setter, culture, ConvertToString);
} }
/// <summary> /// <summary>
@ -363,14 +365,16 @@ namespace Microsoft.AspNetCore.Components
/// <param name="receiver"></param> /// <param name="receiver"></param>
/// <param name="setter"></param> /// <param name="setter"></param>
/// <param name="existingValue"></param> /// <param name="existingValue"></param>
/// <param name="culture"></param>
/// <returns></returns> /// <returns></returns>
public static EventCallback<UIChangeEventArgs> CreateBinder( public static EventCallback<UIChangeEventArgs> CreateBinder(
this EventCallbackFactory factory, this EventCallbackFactory factory,
object receiver, object receiver,
Action<bool> setter, Action<bool> setter,
bool existingValue) bool existingValue,
CultureInfo culture = null)
{ {
return CreateBinderCore<bool>(factory, receiver, setter, ConvertToBool); return CreateBinderCore<bool>(factory, receiver, setter, culture, ConvertToBool);
} }
/// <summary> /// <summary>
@ -380,14 +384,16 @@ namespace Microsoft.AspNetCore.Components
/// <param name="receiver"></param> /// <param name="receiver"></param>
/// <param name="setter"></param> /// <param name="setter"></param>
/// <param name="existingValue"></param> /// <param name="existingValue"></param>
/// <param name="culture"></param>
/// <returns></returns> /// <returns></returns>
public static EventCallback<UIChangeEventArgs> CreateBinder( public static EventCallback<UIChangeEventArgs> CreateBinder(
this EventCallbackFactory factory, this EventCallbackFactory factory,
object receiver, object receiver,
Action<bool?> setter, Action<bool?> setter,
bool? existingValue) bool? existingValue,
CultureInfo culture = null)
{ {
return CreateBinderCore<bool?>(factory, receiver, setter, ConvertToNullableBool); return CreateBinderCore<bool?>(factory, receiver, setter, culture, ConvertToNullableBool);
} }
/// <summary> /// <summary>
@ -397,14 +403,16 @@ namespace Microsoft.AspNetCore.Components
/// <param name="receiver"></param> /// <param name="receiver"></param>
/// <param name="setter"></param> /// <param name="setter"></param>
/// <param name="existingValue"></param> /// <param name="existingValue"></param>
/// <param name="culture"></param>
/// <returns></returns> /// <returns></returns>
public static EventCallback<UIChangeEventArgs> CreateBinder( public static EventCallback<UIChangeEventArgs> CreateBinder(
this EventCallbackFactory factory, this EventCallbackFactory factory,
object receiver, object receiver,
Action<int> setter, Action<int> setter,
int existingValue) int existingValue,
CultureInfo culture = null)
{ {
return CreateBinderCore<int>(factory, receiver, setter, ConvertToInt); return CreateBinderCore<int>(factory, receiver, setter, culture, ConvertToInt);
} }
/// <summary> /// <summary>
@ -414,14 +422,16 @@ namespace Microsoft.AspNetCore.Components
/// <param name="receiver"></param> /// <param name="receiver"></param>
/// <param name="setter"></param> /// <param name="setter"></param>
/// <param name="existingValue"></param> /// <param name="existingValue"></param>
/// <param name="culture"></param>
/// <returns></returns> /// <returns></returns>
public static EventCallback<UIChangeEventArgs> CreateBinder( public static EventCallback<UIChangeEventArgs> CreateBinder(
this EventCallbackFactory factory, this EventCallbackFactory factory,
object receiver, object receiver,
Action<int?> setter, Action<int?> setter,
int? existingValue) int? existingValue,
CultureInfo culture = null)
{ {
return CreateBinderCore<int?>(factory, receiver, setter, ConvertToNullableInt); return CreateBinderCore<int?>(factory, receiver, setter, culture, ConvertToNullableInt);
} }
/// <summary> /// <summary>
@ -431,14 +441,16 @@ namespace Microsoft.AspNetCore.Components
/// <param name="receiver"></param> /// <param name="receiver"></param>
/// <param name="setter"></param> /// <param name="setter"></param>
/// <param name="existingValue"></param> /// <param name="existingValue"></param>
/// <param name="culture"></param>
/// <returns></returns> /// <returns></returns>
public static EventCallback<UIChangeEventArgs> CreateBinder( public static EventCallback<UIChangeEventArgs> CreateBinder(
this EventCallbackFactory factory, this EventCallbackFactory factory,
object receiver, object receiver,
Action<long> setter, Action<long> setter,
long existingValue) long existingValue,
CultureInfo culture = null)
{ {
return CreateBinderCore<long>(factory, receiver, setter, ConvertToLong); return CreateBinderCore<long>(factory, receiver, setter, culture, ConvertToLong);
} }
/// <summary> /// <summary>
@ -448,14 +460,16 @@ namespace Microsoft.AspNetCore.Components
/// <param name="receiver"></param> /// <param name="receiver"></param>
/// <param name="setter"></param> /// <param name="setter"></param>
/// <param name="existingValue"></param> /// <param name="existingValue"></param>
/// <param name="culture"></param>
/// <returns></returns> /// <returns></returns>
public static EventCallback<UIChangeEventArgs> CreateBinder( public static EventCallback<UIChangeEventArgs> CreateBinder(
this EventCallbackFactory factory, this EventCallbackFactory factory,
object receiver, object receiver,
Action<long?> setter, Action<long?> setter,
long? existingValue) long? existingValue,
CultureInfo culture = null)
{ {
return CreateBinderCore<long?>(factory, receiver, setter, ConvertToNullableLong); return CreateBinderCore<long?>(factory, receiver, setter, culture, ConvertToNullableLong);
} }
/// <summary> /// <summary>
@ -465,14 +479,16 @@ namespace Microsoft.AspNetCore.Components
/// <param name="receiver"></param> /// <param name="receiver"></param>
/// <param name="setter"></param> /// <param name="setter"></param>
/// <param name="existingValue"></param> /// <param name="existingValue"></param>
/// <param name="culture"></param>
/// <returns></returns> /// <returns></returns>
public static EventCallback<UIChangeEventArgs> CreateBinder( public static EventCallback<UIChangeEventArgs> CreateBinder(
this EventCallbackFactory factory, this EventCallbackFactory factory,
object receiver, object receiver,
Action<float> setter, Action<float> setter,
float existingValue) float existingValue,
CultureInfo culture = null)
{ {
return CreateBinderCore<float>(factory, receiver, setter, ConvertToFloat); return CreateBinderCore<float>(factory, receiver, setter, culture, ConvertToFloat);
} }
/// <summary> /// <summary>
@ -482,14 +498,16 @@ namespace Microsoft.AspNetCore.Components
/// <param name="receiver"></param> /// <param name="receiver"></param>
/// <param name="setter"></param> /// <param name="setter"></param>
/// <param name="existingValue"></param> /// <param name="existingValue"></param>
/// <param name="culture"></param>
/// <returns></returns> /// <returns></returns>
public static EventCallback<UIChangeEventArgs> CreateBinder( public static EventCallback<UIChangeEventArgs> CreateBinder(
this EventCallbackFactory factory, this EventCallbackFactory factory,
object receiver, object receiver,
Action<float?> setter, Action<float?> setter,
float? existingValue) float? existingValue,
CultureInfo culture = null)
{ {
return CreateBinderCore<float?>(factory, receiver, setter, ConvertToNullableFloat); return CreateBinderCore<float?>(factory, receiver, setter, culture, ConvertToNullableFloat);
} }
/// <summary> /// <summary>
@ -499,14 +517,16 @@ namespace Microsoft.AspNetCore.Components
/// <param name="receiver"></param> /// <param name="receiver"></param>
/// <param name="setter"></param> /// <param name="setter"></param>
/// <param name="existingValue"></param> /// <param name="existingValue"></param>
/// <param name="culture"></param>
/// <returns></returns> /// <returns></returns>
public static EventCallback<UIChangeEventArgs> CreateBinder( public static EventCallback<UIChangeEventArgs> CreateBinder(
this EventCallbackFactory factory, this EventCallbackFactory factory,
object receiver, object receiver,
Action<double> setter, Action<double> setter,
double existingValue) double existingValue,
CultureInfo culture = null)
{ {
return CreateBinderCore<double>(factory, receiver, setter, ConvertToDouble); return CreateBinderCore<double>(factory, receiver, setter, culture, ConvertToDouble);
} }
/// <summary> /// <summary>
@ -516,14 +536,16 @@ namespace Microsoft.AspNetCore.Components
/// <param name="receiver"></param> /// <param name="receiver"></param>
/// <param name="setter"></param> /// <param name="setter"></param>
/// <param name="existingValue"></param> /// <param name="existingValue"></param>
/// <param name="culture"></param>
/// <returns></returns> /// <returns></returns>
public static EventCallback<UIChangeEventArgs> CreateBinder( public static EventCallback<UIChangeEventArgs> CreateBinder(
this EventCallbackFactory factory, this EventCallbackFactory factory,
object receiver, object receiver,
Action<double?> setter, Action<double?> setter,
double? existingValue) double? existingValue,
CultureInfo culture = null)
{ {
return CreateBinderCore<double?>(factory, receiver, setter, ConvertToNullableDouble); return CreateBinderCore<double?>(factory, receiver, setter, culture, ConvertToNullableDouble);
} }
/// <summary> /// <summary>
@ -533,14 +555,16 @@ namespace Microsoft.AspNetCore.Components
/// <param name="receiver"></param> /// <param name="receiver"></param>
/// <param name="setter"></param> /// <param name="setter"></param>
/// <param name="existingValue"></param> /// <param name="existingValue"></param>
/// <param name="culture"></param>
/// <returns></returns> /// <returns></returns>
public static EventCallback<UIChangeEventArgs> CreateBinder( public static EventCallback<UIChangeEventArgs> CreateBinder(
this EventCallbackFactory factory, this EventCallbackFactory factory,
object receiver, object receiver,
Action<decimal> setter, Action<decimal> setter,
decimal existingValue) decimal existingValue,
CultureInfo culture = null)
{ {
return CreateBinderCore<decimal>(factory, receiver, setter, ConvertToDecimal); return CreateBinderCore<decimal>(factory, receiver, setter, culture, ConvertToDecimal);
} }
/// <summary> /// <summary>
@ -550,14 +574,16 @@ namespace Microsoft.AspNetCore.Components
/// <param name="receiver"></param> /// <param name="receiver"></param>
/// <param name="setter"></param> /// <param name="setter"></param>
/// <param name="existingValue"></param> /// <param name="existingValue"></param>
/// <param name="culture"></param>
/// <returns></returns> /// <returns></returns>
public static EventCallback<UIChangeEventArgs> CreateBinder( public static EventCallback<UIChangeEventArgs> CreateBinder(
this EventCallbackFactory factory, this EventCallbackFactory factory,
object receiver, object receiver,
Action<decimal?> setter, Action<decimal?> setter,
decimal? existingValue) decimal? existingValue,
CultureInfo culture = null)
{ {
return CreateBinderCore<decimal?>(factory, receiver, setter, ConvertToNullableDecimal); return CreateBinderCore<decimal?>(factory, receiver, setter, culture, ConvertToNullableDecimal);
} }
/// <summary> /// <summary>
@ -567,14 +593,16 @@ namespace Microsoft.AspNetCore.Components
/// <param name="receiver"></param> /// <param name="receiver"></param>
/// <param name="setter"></param> /// <param name="setter"></param>
/// <param name="existingValue"></param> /// <param name="existingValue"></param>
/// <param name="culture"></param>
/// <returns></returns> /// <returns></returns>
public static EventCallback<UIChangeEventArgs> CreateBinder( public static EventCallback<UIChangeEventArgs> CreateBinder(
this EventCallbackFactory factory, this EventCallbackFactory factory,
object receiver, object receiver,
Action<DateTime> setter, Action<DateTime> setter,
DateTime existingValue) DateTime existingValue,
CultureInfo culture = null)
{ {
return CreateBinderCore<DateTime>(factory, receiver, setter, ConvertToDateTime); return CreateBinderCore<DateTime>(factory, receiver, setter, culture, ConvertToDateTime);
} }
/// <summary> /// <summary>
@ -584,14 +612,16 @@ namespace Microsoft.AspNetCore.Components
/// <param name="receiver"></param> /// <param name="receiver"></param>
/// <param name="setter"></param> /// <param name="setter"></param>
/// <param name="existingValue"></param> /// <param name="existingValue"></param>
/// <param name="culture"></param>
/// <returns></returns> /// <returns></returns>
public static EventCallback<UIChangeEventArgs> CreateBinder( public static EventCallback<UIChangeEventArgs> CreateBinder(
this EventCallbackFactory factory, this EventCallbackFactory factory,
object receiver, object receiver,
Action<DateTime?> setter, Action<DateTime?> setter,
DateTime? existingValue) DateTime? existingValue,
CultureInfo culture = null)
{ {
return CreateBinderCore<DateTime?>(factory, receiver, setter, ConvertToNullableDateTime); return CreateBinderCore<DateTime?>(factory, receiver, setter, culture, ConvertToNullableDateTime);
} }
/// <summary> /// <summary>
@ -602,13 +632,15 @@ namespace Microsoft.AspNetCore.Components
/// <param name="setter"></param> /// <param name="setter"></param>
/// <param name="existingValue"></param> /// <param name="existingValue"></param>
/// <param name="format"></param> /// <param name="format"></param>
/// <param name="culture"></param>
/// <returns></returns> /// <returns></returns>
public static EventCallback<UIChangeEventArgs> CreateBinder( public static EventCallback<UIChangeEventArgs> CreateBinder(
this EventCallbackFactory factory, this EventCallbackFactory factory,
object receiver, object receiver,
Action<DateTime> setter, Action<DateTime> setter,
DateTime existingValue, DateTime existingValue,
string format) string format,
CultureInfo culture = null)
{ {
// Avoiding CreateBinderCore so we can avoid an extra allocating lambda // Avoiding CreateBinderCore so we can avoid an extra allocating lambda
// when a format is used. // when a format is used.
@ -618,7 +650,7 @@ namespace Microsoft.AspNetCore.Components
var converted = false; var converted = false;
try try
{ {
value = ConvertDateTime(e.Value, format); value = ConvertDateTime(e.Value, culture, format);
converted = true; converted = true;
} }
catch catch
@ -633,20 +665,20 @@ namespace Microsoft.AspNetCore.Components
}; };
return factory.Create<UIChangeEventArgs>(receiver, callback); return factory.Create<UIChangeEventArgs>(receiver, callback);
static DateTime ConvertDateTime(object obj, string format) static DateTime ConvertDateTime(object obj, CultureInfo culture, string format)
{ {
var text = (string)obj; var text = (string)obj;
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
{ {
return default; return default;
} }
else if (format != null && DateTime.TryParseExact(text, format, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var value)) else if (format != null && DateTime.TryParseExact(text, format, culture ?? CultureInfo.CurrentCulture, DateTimeStyles.RoundtripKind, out var value))
{ {
return value; return value;
} }
else else
{ {
return DateTime.Parse(text); return DateTime.Parse(text, culture ?? CultureInfo.CurrentCulture, DateTimeStyles.RoundtripKind);
} }
} }
} }
@ -659,20 +691,23 @@ namespace Microsoft.AspNetCore.Components
/// <param name="receiver"></param> /// <param name="receiver"></param>
/// <param name="setter"></param> /// <param name="setter"></param>
/// <param name="existingValue"></param> /// <param name="existingValue"></param>
/// <param name="culture"></param>
/// <returns></returns> /// <returns></returns>
public static EventCallback<UIChangeEventArgs> CreateBinder<T>( public static EventCallback<UIChangeEventArgs> CreateBinder<T>(
this EventCallbackFactory factory, this EventCallbackFactory factory,
object receiver, object receiver,
Action<T> setter, Action<T> setter,
T existingValue) T existingValue,
CultureInfo culture = null)
{ {
return CreateBinderCore<T>(factory, receiver, setter, BinderConverterCache.Get<T>()); return CreateBinderCore<T>(factory, receiver, setter, culture, BinderConverterCache.Get<T>());
} }
private static EventCallback<UIChangeEventArgs> CreateBinderCore<T>( private static EventCallback<UIChangeEventArgs> CreateBinderCore<T>(
this EventCallbackFactory factory, this EventCallbackFactory factory,
object receiver, object receiver,
Action<T> setter, Action<T> setter,
CultureInfo culture,
BindConverter<T> converter) BindConverter<T> converter)
{ {
Action<UIChangeEventArgs> callback = e => Action<UIChangeEventArgs> callback = e =>
@ -681,7 +716,7 @@ namespace Microsoft.AspNetCore.Components
var converted = false; var converted = false;
try try
{ {
converted = converter(e.Value, out value); converted = converter(e.Value, culture, out value);
} }
catch catch
{ {
@ -822,7 +857,7 @@ namespace Microsoft.AspNetCore.Components
return ConvertWithTypeConverter; return ConvertWithTypeConverter;
bool ConvertWithTypeConverter(object obj, out T value) bool ConvertWithTypeConverter(object obj, CultureInfo culture, out T value)
{ {
var text = (string)obj; var text = (string)obj;
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
@ -832,7 +867,7 @@ namespace Microsoft.AspNetCore.Components
} }
// We intentionally close-over the TypeConverter to cache it. The TypeDescriptor infrastructure is slow. // We intentionally close-over the TypeConverter to cache it. The TypeDescriptor infrastructure is slow.
var converted = typeConverter.ConvertFromString(context: null, CultureInfo.CurrentCulture, text); var converted = typeConverter.ConvertFromString(context: null, culture ?? CultureInfo.CurrentCulture, text);
if (converted == null) if (converted == null)
{ {
value = default; value = default;

View File

@ -5,6 +5,7 @@ using System;
using System.ComponentModel; using System.ComponentModel;
using System.Globalization; using System.Globalization;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Testing;
using Xunit; using Xunit;
namespace Microsoft.AspNetCore.Components namespace Microsoft.AspNetCore.Components
@ -515,6 +516,45 @@ namespace Microsoft.AspNetCore.Components
ex.Message); ex.Message);
} }
[Fact]
[ReplaceCulture("fr-FR", "fr-FR")]
public async Task CreateBinder_NumericType_WithCurrentCulture()
{
// Arrange
var value = 17_000;
var component = new EventCountingComponent();
Action<int> setter = (_) => value = _;
var binder = EventCallback.Factory.CreateBinder(component, setter, value, culture: null);
var expectedValue = 42_000;
// Act
await binder.InvokeAsync(new UIChangeEventArgs() { Value = "42 000,00", });
Assert.Equal(expectedValue, value);
Assert.Equal(1, component.Count);
}
[Fact]
public async Task CreateBinder_NumericType_WithInvariantCulture()
{
// Arrange
var value = 17_000;
var component = new EventCountingComponent();
Action<int> setter = (_) => value = _;
var binder = EventCallback.Factory.CreateBinder(component, setter, value, CultureInfo.InvariantCulture);
var expectedValue = 42_000;
// Act
await binder.InvokeAsync(new UIChangeEventArgs() { Value = "42,000.00", });
Assert.Equal(expectedValue, value);
Assert.Equal(1, component.Count);
}
private class EventCountingComponent : IComponent, IHandleEvent private class EventCountingComponent : IComponent, IHandleEvent
{ {
public int Count; public int Count;