Skip to content

Dapper type converter generation #85

Description

@SamuelMcAravey

We need to go through and add in dapper type converters to the library. We're slowly trying to make our types be more type safe. For example, we've changed the owner token to be a record struct, as you can see here. But it fails tests because there's no direct translation in dapper from a GUID to, in this case, an owner token type. So we need to find either a way to intrinsically allow these types to be type convertible or generate dapper type converters for all the different custom types that we have.

// <auto-generated/>


#nullable enable

namespace Bravellian.Platform;

using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;

[JsonConverter(typeof(OwnerTokenJsonConverter))]
[TypeConverter(typeof(OwnerTokenTypeConverter))]
public readonly partial record struct OwnerToken
        : IComparable,
          IComparable<OwnerToken>,
          IEquatable<OwnerToken>,
          ISpanParsable<OwnerToken>,
          IParsable<OwnerToken>
{
    public const string ExactValidationRegexString = $"^{FullValidationRegexString}$";
    public const string FullValidationRegexString = "(?#GUID match)(?![({]?[0]{8}[-]?(?>[0]{4}[-]?){3}[0]{12}[})]?)[({]?[a-fA-F0-9]{8}[-]?(?>[a-fA-F0-9]{4}[-]?){3}[a-fA-F0-9]{12}[})]?";

    public static readonly OwnerToken Empty = new(Guid.Empty);

    public OwnerToken(Guid value)
    {
        this.Value = value;
    }

    public Guid Value { get; init; }

    public static OwnerToken GenerateNew() => new(Guid.NewGuid());

    public static OwnerToken From(Guid value) => new(value);

    public static OwnerToken? From(Guid? value) => value.HasValue ? new(value.Value) : null;

    public static OwnerToken Parse(ReadOnlySpan<char> s, IFormatProvider? provider)
    {
        var id = Guid.Parse(s, provider);
        return new OwnerToken(id);
    }

    public static OwnerToken Parse([StringSyntax(StringSyntaxAttribute.GuidFormat)] string s, IFormatProvider? provider)
    {
        var id = Guid.Parse(s, provider);
        return new OwnerToken(id);
    }

    public static OwnerToken Parse([StringSyntax(StringSyntaxAttribute.GuidFormat)] string value) => new(Guid.Parse(value));

    public static bool TryParse(ReadOnlySpan<char> s, IFormatProvider? provider, out OwnerToken result)
    {
        if (Guid.TryParse(s, provider, out Guid id))
        {
            result = new OwnerToken(id);
            return true;
        }

        result = default;
        return false;
    }

    public static bool TryParse([StringSyntax(StringSyntaxAttribute.GuidFormat)] [NotNullWhen(true)] string? s, IFormatProvider? provider, out OwnerToken result)
    {
        if (Guid.TryParse(s, provider, out Guid id))
        {
            result = new OwnerToken(id);
            return true;
        }

        result = default;
        return false;
    }

    public static OwnerToken? TryParse([StringSyntax(StringSyntaxAttribute.GuidFormat)] string? value)
    {
        if (Guid.TryParse(value, out Guid result))
        {
            return new OwnerToken(result);
        }

        return null;
    }

    public static bool TryParse([StringSyntax(StringSyntaxAttribute.GuidFormat)] string? value, out OwnerToken id)
    {
        if (Guid.TryParse(value, out Guid result))
        {
            id = new OwnerToken(result);
            return true;
        }

        id = default;
        return false;
    }

    public int CompareTo(OwnerToken other)
    {
        return this.Value.CompareTo(other.Value);
    }

    public int CompareTo(object? obj)
    {
        if (obj is OwnerToken id)
        {
            return this.Value.CompareTo(id.Value);
        }

        return this.Value.CompareTo(obj);
    }

    public static bool operator <(OwnerToken left, OwnerToken right) => left.CompareTo(right) < 0;

    public static bool operator <=(OwnerToken left, OwnerToken right) => left.CompareTo(right) <= 0;

    public static bool operator >(OwnerToken left, OwnerToken right) => left.CompareTo(right) > 0;

    public static bool operator >=(OwnerToken left, OwnerToken right) => left.CompareTo(right) >= 0;

    public bool Equals(OwnerToken other)
    {
        return this.Value.Equals(other.Value);
    }

    public override int GetHashCode()
    {
        return this.Value.GetHashCode();
    }

    public override string ToString() => this.Value.ToString("N");

    public string ToString(string format) => this.Value.ToString(format);

    public class OwnerTokenJsonConverter : JsonConverter<OwnerToken>
    {
        public override OwnerToken Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            var s = reader.GetString();

            if (!string.IsNullOrEmpty(s) && Guid.TryParse(s, out Guid id))
            {
                return new OwnerToken(id);
            }

            throw new JsonException();
        }

        public override void Write(Utf8JsonWriter writer, OwnerToken value, JsonSerializerOptions options) =>
            writer.WriteStringValue(value.Value.ToString());

        public override void WriteAsPropertyName(
            Utf8JsonWriter writer,
            OwnerToken value,
            JsonSerializerOptions options) =>
                writer.WritePropertyName(value.ToString());

        public override OwnerToken ReadAsPropertyName(
            ref Utf8JsonReader reader,
            Type typeToConvert,
            JsonSerializerOptions options) =>
                Read(ref reader, typeToConvert, options);
    }

    // TypeConverter for OwnerToken to and from string and Guid
    public class OwnerTokenTypeConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) =>
            sourceType == typeof(string) || sourceType == typeof(Guid) || base.CanConvertFrom(context, sourceType);

        public override bool CanConvertTo(ITypeDescriptorContext? context, [NotNullWhen(true)] Type? destinationType) =>
            destinationType == typeof(string) || destinationType == typeof(Guid) || base.CanConvertTo(context, destinationType);

        public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
        {
            if (value is string s)
            {
                return TryParse(s) ?? default;
            }

            if (value is Guid g)
            {
                return new OwnerToken(g);
            }

            return base.ConvertFrom(context, culture, value) ?? default;
        }

        public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
        {
            if (value is OwnerToken type)
            {
                if (destinationType == typeof(string))
                {
                    return type.ToString();
                }

                if (destinationType == typeof(Guid))
                {
                    return type.Value;
                }
            }

            return base.ConvertTo(context, culture, value, destinationType);
        }
    }
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions