lucasteles / Strongly

💪🏾 A strongly-typed domain values source-generator
MIT License
35 stars 6 forks source link

Ef core converters not being registered #12

Closed adrianotr closed 6 months ago

adrianotr commented 6 months ago

Hi,

First of all, congrats on the project! I was thinking about creating a source generator myself when I came across this project. I could not have made a better job really. This is just perfect!

I'm using UseStronglyTypeConverters from the Strongly.EFCore package but my converters are not being registered.

If I set a breakpoint at the line above I can see that it always returns null for my ID structs:

https://github.com/lucasteles/Strongly/blob/842a3d49fae66e755b8560753610634a64c51c40/src/Strongly.EFCore/StrongTypedValueConverterSelector.cs#L38

What is that line trying to get exactly?

Here is the struct generated code:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by the Strongly source generator
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

#pragma warning disable 1591 // publicly visible type or member must be documented

#nullable enable
namespace X
{
    [System.Text.Json.Serialization.JsonConverter(typeof(AuctionIdSystemTextJsonConverter))]
    [System.ComponentModel.TypeConverter(typeof(AuctionIdTypeConverter))]

[System.Diagnostics.DebuggerDisplay("{Value}", Type = "AuctionId")]
#if NET7_0_OR_GREATER
readonly partial struct AuctionId : System.IComparable<AuctionId>, System.IEquatable<AuctionId>, System.IFormattable, System.IParsable<AuctionId>
#else
readonly partial struct AuctionId : System.IComparable<AuctionId>, System.IEquatable<AuctionId>, System.IFormattable
#endif
{
    public System.Guid Value { get; }

    public AuctionId(System.Guid value)
    {
        Value = value;
    }

    public override int GetHashCode() => Value.GetHashCode();
    public static bool operator ==(AuctionId a, AuctionId b) => a.Equals(b);
    public static bool operator !=(AuctionId a, AuctionId b) => !(a == b);
    public override string ToString() => Value.ToString();
    public override bool Equals(object? obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        return obj is AuctionId other && Equals(other);
    }
    public bool Equals(AuctionId other) => this.Value.Equals(other.Value);

    public static readonly AuctionId Empty = new AuctionId(System.Guid.Empty);

        public static AuctionId New() => new AuctionId(System.Guid.NewGuid());
    public int CompareTo(AuctionId other) => Value.CompareTo(other.Value);

    public string ToString(string? format, System.IFormatProvider? formatProvider) =>
        this.Value.ToString(format, formatProvider);

    public static AuctionId Parse(string value) => 
        new AuctionId(System.Guid.Parse(value));

    public static bool TryParse(
        [System.Diagnostics.CodeAnalysis.NotNullWhen(true)]string? value, 
        out AuctionId result)
    {
        if (System.Guid.TryParse(value, out System.Guid parseResult))
        {
            result = new AuctionId(parseResult);
            return true;
        }
        result = default;
        return false;
    }

#if NET7_0_OR_GREATER
    public static AuctionId Parse(string value, System.IFormatProvider? provider) => 
        new AuctionId(System.Guid.Parse(value, provider));

    public static bool TryParse(
        [System.Diagnostics.CodeAnalysis.NotNullWhen(true)]string? value, 
        System.IFormatProvider? provider, 
        out AuctionId result)
    {
        if (System.Guid.TryParse(
                value,
                provider, 
                out System.Guid parseResult))
        {
            result = new AuctionId(parseResult);
            return true;
        }
        result = default;
        return false;
    }
#endif

class AuctionIdTypeConverter : System.ComponentModel.TypeConverter
{
    public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Type sourceType)
    {
        return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
    }

    public override object? ConvertFrom(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value)
    {
        return value switch
        {
            System.Guid guidValue => new AuctionId(guidValue),
            string stringValue when !string.IsNullOrEmpty(stringValue) && System.Guid.TryParse(stringValue, out var result) => new AuctionId(result),
            _ => base.ConvertFrom(context, culture, value),
        };
    }

    public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Type? sourceType)
    {
        return sourceType == typeof(System.Guid) || sourceType == typeof(string) || base.CanConvertTo(context, sourceType);
    }

    public override object? ConvertTo(System.ComponentModel.ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, System.Type destinationType)
    {
        if (value is AuctionId idValue)
        {
            if (destinationType == typeof(System.Guid))
            {
                return idValue.Value;
            }

            if (destinationType == typeof(string))
            {
                return idValue.Value.ToString();
            }
        }

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

class AuctionIdSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter<AuctionId>
{
    public override AuctionId Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
    {
        return new AuctionId(System.Guid.Parse(reader.GetString()!));
    }

    public override void Write(System.Text.Json.Utf8JsonWriter writer, AuctionId value, System.Text.Json.JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.Value);
    }
}

    }
}
adrianotr commented 6 months ago

Sorry, I just noticed that I messed up when I moved my code to another project. The Ef converter was not generated because it was missing the [assembly:StronglyTypedIdDefaults].