ardalis/SmartEnum

JsonConverter doesn't support string Value type

Aperta

#111 aperta il 12 mar 2021

 (5 commenti) (1 reazione) (0 assegnatari)C# (185 fork)github user discovery
buggood first issuehelp wanted

Metriche repository

Star
 (2420 stelle)
Metriche merge PR
 (Nessuna PR mergiata in 30 g)

Descrizione

I have a usecase where we need to deal with string values as the backing value for an enumeration. As an example, imagine a Customer Type stored in the database as a string code:

  • Preferred = "pref"
  • Elite = "el"
  • Regular = "reg"

SmartEnum can handle that if you define your type as SmartEnum<CustomerTypeCode, string>. However the associated SmartEnum.JsonNet package doesn't allow this because it constraints the TValue to be a struct, which string is not.

Example:

public class CustomerTypeCode: SmartEnum<CustomerType, string>
{
    public static readonly CustomerTypeCode Regular = new CustomerTypeCode(nameof(Regular), "reg");
    public static readonly CustomerTypeCode Preferred = new CustomerTypeCode(nameof(Preferred), "pref");
    public static readonly CustomerTypeCode Elite = new CustomerTypeCode(nameof(Elite), "el");

    public DecisionResponseCode(string name, string value) : base(name, value) { }
}

public class Customer
{
    // ERROR: The type 'string' must be non-nullable value type in order to use it as parameter 'TValue' ...
    [JsonConverter(typeof(SmartEnumValueConverter<CustomerTypeCode, string>))]
    public CustomerTypeCode Code { get; set; }
}

I get a compiler error when trying to use either SmartEnumValueConverter<CustomerTypeCode, string> or SmartEnumNameConverter<CustomerTypeCode, string> because the generic type constraints of TValue include struct, whereas TValue in SmartEnum doesn't have this constraint.

public abstract class SmartEnum<TEnum, TValue> 
    : IEquatable<SmartEnum<TEnum, TValue>>, 
      IComparable<SmartEnum<TEnum, TValue>> 
      where TEnum : SmartEnum<TEnum, TValue> 
      where TValue : IEquatable<TValue>, IComparable<TValue>
public class SmartEnumValueConverter<TEnum, TValue> 
    : JsonConverter<TEnum> 
      where TEnum : SmartEnum<TEnum, TValue> 
      where TValue : struct, IEquatable<TValue>, IComparable<TValue>

Is there any reason to not use string as your backing value, that this type constraint is in place? Or can the restriction be removed in a future update? For now I can write my own type converter, but I figured I'd submit this as a bug (in case it is one).

Thanks!

Guida contributor