Enums.NET icon indicating copy to clipboard operation
Enums.NET copied to clipboard

[Feature] Custom EnumFormat with AllowMultiple

Open Crossbow78 opened this issue 4 years ago • 2 comments

Always looking for the impossible, I found myself in need of the following:

[AttributeUsage(AttributeTargets.Field, AllowMultiple = true)]
internal class AliasAttribute : Attribute
{
   public AliasAttribute(string text) => Text = text;
   public string Text { get; set; }
}

public enum Direction
{
   [Alias("^")]
   [Alias("N")]
   North,

   [Alias("v")]
   [Alias("S")]
   South
}

var aliasFormat = Enums.RegisterCustomEnumFormat(x => x.Attributes.Get<AliasAttribute>()?.Text);
var direction = Enums.Parse<Direction>("N", ignoreCase: true, aliasFormat);

The above fails with "'string was not recognized as being a member of Direction (Parameter 'value')'" because it will only work with the value of the first attribute on each field. I'm wondering whether I'm missing a clever trick with the Enums.RegisterCustomEnumFormat command. But even with a single refactored AliasAttribute per field that could store multiple values (eg. [Alias("N", "^")]), I wouldn't know how to achieve my goal...

Crossbow78 avatar Nov 21 '20 23:11 Crossbow78

EnumFormats support parsing and outputting. If they were allowed to support multiple values for parsing Enums.NET would not know what version for outputting with the AsString method. I'd suggest you create multiple custom enum formats for up to how many alias's you need to support so something like this.

var aliasFormat1 = Enums.RegisterCustomEnumFormat(x => x.Attributes.GetAll<AliasAttribute>().FirstOrDefault()?.Text);
var aliasFormat2 = Enums.RegisterCustomEnumFormat(x => x.Attributes.GetAll<AliasAttribute>().Skip(1).FirstOrDefault()?.Text);
var direction = Enums.Parse<Direction>("N", ignoreCase: true, aliasFormat1, aliasFormat2);

TylerBrinkley avatar Nov 23 '20 14:11 TylerBrinkley

Ah, I hadn't thought of the ambiguity with AsString. But of course, the same can be said about the current parsing behavior which only considers the first attribute to do its job.

Forgive me for running my imagination, but could this short-hand work? public static EnumFormat RegisterCustomEnumFormat<T>(Func<T, string> textResolver) where T: Attribute It would apply to every EnumMember when parsing, and could easily support multiple attributes.

My first example would be:

var aliasFormat = Enums.RegisterCustomEnumFormat<AliasAttribute>(x => x.Text); // NOTE: unsupported syntax
var direction = Enums.Parse<Direction>("N", ignoreCase: true, aliasFormat);    // Evaluates to 'North'
var txt = direction.AsString(aliasFormat);                                     // Evaluates to '^' (first match)

Either way, thanks for suggesting the work-around.

Crossbow78 avatar Nov 23 '20 22:11 Crossbow78