Skip to content

Commit

Permalink
Add StringEnumReader which converts strings to StringEnums
Browse files Browse the repository at this point in the history
Because we serialize with json.net and deserialize with System.Text.Json (involuntarily through jsruntime), we need a write-converter for json.net and a read-converter for system.text.json. sadly a lot of features are not yet present in system.text.json and so we can't use one converter attribute for the base-class but need one for every enum. This should change in .Net 5; progress is tracked at https://github.com/dotnet/corefx/issues/39905.
  • Loading branch information
Joelius300 committed Jan 4, 2020
1 parent f885d0c commit b4883b7
Show file tree
Hide file tree
Showing 21 changed files with 136 additions and 25 deletions.
6 changes: 5 additions & 1 deletion src/ChartJs.Blazor/ChartJS/Common/Enums/AxisType.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
namespace ChartJs.Blazor.ChartJS.Common.Enums
using ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter;
using System.Text.Json.Serialization;

namespace ChartJs.Blazor.ChartJS.Common.Enums
{
/// <summary>
/// As per documentation here https://www.chartjs.org/docs/latest/axes/cartesian/
/// </summary>
[JsonConverter(typeof(JsonStringEnumReader<AxisType>))]
public sealed class AxisType : StringEnum
{
/// <summary>
Expand Down
6 changes: 5 additions & 1 deletion src/ChartJs.Blazor/ChartJS/Common/Enums/BorderAlign.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
namespace ChartJs.Blazor.ChartJS.Common.Enums
using ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter;
using System.Text.Json.Serialization;

namespace ChartJs.Blazor.ChartJS.Common.Enums
{
/// <summary>
/// Specifies the border alignment of a <see cref="PieChart"/> and a <see cref="PolarAreaChart"/>.
/// <para>As per documentation here https://www.chartjs.org/docs/latest/charts/doughnut.html#border-alignment </para>
/// </summary>
[JsonConverter(typeof(JsonStringEnumReader<BorderAlign>))]
public sealed class BorderAlign : StringEnum
{
/// <summary>
Expand Down
6 changes: 5 additions & 1 deletion src/ChartJs.Blazor/ChartJS/Common/Enums/BorderCapStyle.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
namespace ChartJs.Blazor.ChartJS.Common.Enums
using ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter;
using System.Text.Json.Serialization;

namespace ChartJs.Blazor.ChartJS.Common.Enums
{
/// <summary>
/// Specifies the border cap style.
/// <para>As per documentation here https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineCap </para>
/// </summary>
[JsonConverter(typeof(JsonStringEnumReader<BorderCapStyle>))]
public sealed class BorderCapStyle : StringEnum
{
/// <summary>
Expand Down
6 changes: 5 additions & 1 deletion src/ChartJs.Blazor/ChartJS/Common/Enums/BorderJoinStyle.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
namespace ChartJs.Blazor.ChartJS.Common.Enums
using ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter;
using System.Text.Json.Serialization;

namespace ChartJs.Blazor.ChartJS.Common.Enums
{
/// <summary>
/// Specifies the border join style.
/// <para>As per documentation here https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin </para>
/// </summary>
[JsonConverter(typeof(JsonStringEnumReader<BorderJoinStyle>))]
public sealed class BorderJoinStyle : StringEnum
{
/// <summary>
Expand Down
6 changes: 5 additions & 1 deletion src/ChartJs.Blazor/ChartJS/Common/Enums/ChartType.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
namespace ChartJs.Blazor.ChartJS.Common.Enums
using ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter;
using System.Text.Json.Serialization;

namespace ChartJs.Blazor.ChartJS.Common.Enums
{
/// <summary>
/// Defines the chart types.
/// </summary>
[JsonConverter(typeof(JsonStringEnumReader<ChartType>))]
public sealed class ChartType : StringEnum
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
namespace ChartJs.Blazor.ChartJS.Common.Enums
using ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter;
using System.Text.Json.Serialization;

namespace ChartJs.Blazor.ChartJS.Common.Enums
{
/// <summary>
/// Specifies the cubic interpolation mode.
/// <para>As per documentation here https://www.chartjs.org/docs/latest/charts/line.html#cubicinterpolationmode </para>
/// </summary>
[JsonConverter(typeof(JsonStringEnumReader<CubicInterpolationMode>))]
public sealed class CubicInterpolationMode : StringEnum
{
/// <summary>
Expand Down
4 changes: 4 additions & 0 deletions src/ChartJs.Blazor/ChartJS/Common/Enums/FontStyle.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
using ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter;
using System.Text.Json.Serialization;

namespace ChartJs.Blazor.ChartJS.Common.Enums
{
/// <summary>
/// Specifies the css font style of text.
/// <para>As per documentation here https://developer.mozilla.org/en-US/docs/Web/CSS/font-style </para>
/// </summary>
[JsonConverter(typeof(JsonStringEnumReader<FontStyle>))]
public sealed class FontStyle : StringEnum
{
/// <summary>
Expand Down
6 changes: 5 additions & 1 deletion src/ChartJs.Blazor/ChartJS/Common/Enums/InteractionMode.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
namespace ChartJs.Blazor.ChartJS.Common.Enums
using ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter;
using System.Text.Json.Serialization;

namespace ChartJs.Blazor.ChartJS.Common.Enums
{
/// <summary>
/// As per documentation here https://www.chartjs.org/docs/latest/general/interactions/modes.html
/// </summary>
[JsonConverter(typeof(JsonStringEnumReader<InteractionMode>))]
public sealed class InteractionMode : StringEnum
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
namespace ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter
{
/// <summary>
/// JsonConverter for converting and writing an ObjectEnum value. This JsonConverter can only write.
/// Newtonsoft JsonConverter for writing an <see cref="ObjectEnum"/> value. This JsonConverter can only write.
/// </summary>
internal class JsonObjectEnumConverter : JsonWriteOnlyConverter<ObjectEnum>
internal class JsonObjectEnumWriter : JsonWriteOnlyConverter<ObjectEnum>
{
public override void WriteJson(JsonWriter writer, ObjectEnum wrapper, JsonSerializer serializer)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter
{
// we need T and the constraint because the you can't use JsonConverter for the base-class
// https://github.com/dotnet/corefx/issues/39905
/// <summary>
/// System.Text.Json JsonConverter for reading <see cref="StringEnum"/>s. The <see cref="StringEnum"/> is created via reflection
/// and does not take in account what values actually exist in the "enum". This is not a big deal
/// because the values that are deserialized using this converter should only come from chart.js and should be mapped correctly
/// to an "enum"-value in that <see cref="StringEnum"/>.
/// </summary>
/// <typeparam name="T">The type of <see cref="StringEnum"/> this converter is for. This is required because System.Text.Json
/// doesn't allow converters for base-classes yet.</typeparam>
internal class JsonStringEnumReader<T> : JsonConverter<T>
where T : StringEnum
{
private static readonly ConcurrentDictionary<Type, ConstructorInfo> s_constructorCache = new ConcurrentDictionary<Type, ConstructorInfo>();

public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
ConstructorInfo constructor = s_constructorCache.GetOrAdd(typeToConvert,
type => type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(string) }, null));

return (T)constructor.Invoke(new[] { reader.GetString() });
}

public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
namespace ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter
{
/// <summary>
/// JsonConverter for converting and writing a StringEnum value. This JsonConverter can only write.
/// Newtonsoft JsonConverter for writing a <see cref="StringEnum"/> value. This JsonConverter can only write.
/// </summary>
internal class JsonStringEnumConverter : JsonWriteOnlyConverter<StringEnum>
internal class JsonStringEnumWriter : JsonWriteOnlyConverter<StringEnum>
{
public override void WriteJson(JsonWriter writer, StringEnum value, JsonSerializer serializer)
{
Expand Down
2 changes: 1 addition & 1 deletion src/ChartJs.Blazor/ChartJS/Common/Enums/ObjectEnum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace ChartJs.Blazor.ChartJS.Common.Enums
/// <summary>
/// Inherit this class if you are in need of a pseudo-Enum which can hold values of different kinds (eg. string, double and bool).
/// </summary>
[JsonConverter(typeof(JsonObjectEnumConverter))]
[JsonConverter(typeof(JsonObjectEnumWriter))]
public abstract class ObjectEnum
{
/// <summary>
Expand Down
4 changes: 4 additions & 0 deletions src/ChartJs.Blazor/ChartJS/Common/Enums/PointStyle.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@

using ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter;
using System.Text.Json.Serialization;

namespace ChartJs.Blazor.ChartJS.Common.Enums
{
/// <summary>
/// Specifies how a data-point on the chart will be styled.
/// <para>As per documentation here https://www.chartjs.org/docs/latest/configuration/elements.html#point-styles </para>
/// <para>Some samples showcasing the different styles can be found here https://www.chartjs.org/samples/latest/charts/line/point-styles.html </para>
/// </summary>
[JsonConverter(typeof(JsonStringEnumReader<PointStyle>))]
public sealed class PointStyle : StringEnum
{
/// <summary>
Expand Down
6 changes: 5 additions & 1 deletion src/ChartJs.Blazor/ChartJS/Common/Enums/Position.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
namespace ChartJs.Blazor.ChartJS.Common.Enums
using ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter;
using System.Text.Json.Serialization;

namespace ChartJs.Blazor.ChartJS.Common.Enums
{
/// <summary>
/// Represents a relative direction or position on a 2D canvas.
/// </summary>
[JsonConverter(typeof(JsonStringEnumReader<Position>))]
public sealed class Position : StringEnum
{
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
Expand Down
6 changes: 5 additions & 1 deletion src/ChartJs.Blazor/ChartJS/Common/Enums/ScaleBound.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
namespace ChartJs.Blazor.ChartJS.Common.Enums
using ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter;
using System.Text.Json.Serialization;

namespace ChartJs.Blazor.ChartJS.Common.Enums
{
/// <summary>
/// Specifies the scale boundary strategy.
/// <para>As per documentation here https://www.chartjs.org/docs/latest/axes/cartesian/time.html#scale-bounds </para>
/// </summary>
[JsonConverter(typeof(JsonStringEnumReader<ScaleBound>))]
public sealed class ScaleBound : StringEnum
{
/// <summary>
Expand Down
6 changes: 4 additions & 2 deletions src/ChartJs.Blazor/ChartJS/Common/Enums/StringEnum.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using Newtonsoft.Json;
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter;

namespace ChartJs.Blazor.ChartJS.Common.Enums
{
[JsonConverter(typeof(JsonStringEnumConverter))]
[Newtonsoft.Json.JsonConverter(typeof(JsonStringEnumWriter))]
public abstract class StringEnum
{
private readonly string _value;
Expand Down
6 changes: 5 additions & 1 deletion src/ChartJs.Blazor/ChartJS/Common/Enums/TickSource.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
namespace ChartJs.Blazor.ChartJS.Common.Enums
using ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter;
using System.Text.Json.Serialization;

namespace ChartJs.Blazor.ChartJS.Common.Enums
{
/// <summary>
/// As per documentation here https://www.chartjs.org/docs/latest/axes/cartesian/time.html#ticks-source
/// </summary>
[JsonConverter(typeof(JsonStringEnumReader<TickSource>))]
public sealed class TickSource : StringEnum
{
/// <summary>
Expand Down
4 changes: 4 additions & 0 deletions src/ChartJs.Blazor/ChartJS/Common/Enums/TimeDistribution.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@

using ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter;
using System.Text.Json.Serialization;

namespace ChartJs.Blazor.ChartJS.Common.Enums
{
/// <summary>
/// As per documentation here https://www.chartjs.org/docs/latest/axes/cartesian/time.html#scale-distribution
/// </summary>
[JsonConverter(typeof(JsonStringEnumReader<TimeDistribution>))]
public sealed class TimeDistribution : StringEnum
{
/// <summary>
Expand Down
9 changes: 7 additions & 2 deletions src/ChartJs.Blazor/ChartJS/Common/Enums/TimeMeasurement.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
namespace ChartJs.Blazor.ChartJS.Common.Enums
using ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter;
using System.Text.Json.Serialization;

namespace ChartJs.Blazor.ChartJS.Common.Enums
{
/// <summary>
/// As per documentation here https://www.chartjs.org/docs/latest/axes/cartesian/time.html#time-units
/// </summary>
///
[JsonConverter(typeof(JsonStringEnumReader<TimeMeasurement>))]
public sealed class TimeMeasurement : StringEnum
{
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
public static TimeMeasurement Millisecond => new TimeMeasurement("millisecond");
public static TimeMeasurement Second => new TimeMeasurement("second");
public static TimeMeasurement Minute => new TimeMeasurement("minute");
Expand All @@ -15,6 +19,7 @@ public sealed class TimeMeasurement : StringEnum
public static TimeMeasurement Month => new TimeMeasurement("month");
public static TimeMeasurement Quarter => new TimeMeasurement("quarter");
public static TimeMeasurement Year => new TimeMeasurement("year");
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member

private TimeMeasurement(string stringRep) : base(stringRep) { }
}
Expand Down
6 changes: 5 additions & 1 deletion src/ChartJs.Blazor/ChartJS/Common/Enums/TooltipPosition.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
namespace ChartJs.Blazor.ChartJS.Common.Enums
using ChartJs.Blazor.ChartJS.Common.Enums.JsonConverter;
using System.Text.Json.Serialization;

namespace ChartJs.Blazor.ChartJS.Common.Enums
{
/// <summary>
/// Specifies where the tooltip will be displayed.
/// <para>As per documentation here https://www.chartjs.org/docs/latest/configuration/tooltip.html#position-modes </para>
/// </summary>
[JsonConverter(typeof(JsonStringEnumReader<TooltipPosition>))]
public sealed class TooltipPosition : StringEnum
{
/// <summary>
Expand Down
19 changes: 14 additions & 5 deletions src/ChartJs.Blazor/ChartJs.Blazor.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit b4883b7

Please sign in to comment.