An open API service indexing awesome lists of open source software.

https://github.com/OhFlowi/FusionReactor.SourceGenerators.EnumExtensions


https://github.com/OhFlowi/FusionReactor.SourceGenerators.EnumExtensions

Last synced: 3 months ago
JSON representation

Awesome Lists containing this project

README

        

[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://raw.githubusercontent.com/OhFlowi/FusionReactor.SourceGenerators.EnumExtensions/master/LICENSE)
[![Nuget](https://img.shields.io/nuget/dt/FusionReactor.SourceGenerators.EnumExtensions?label=Nuget.org%20Downloads&style=flat-square&color=blue)](https://www.nuget.org/packages/FusionReactor.SourceGenerators.EnumExtensions)
[![Nuget](https://img.shields.io/nuget/vpre/FusionReactor.SourceGenerators.EnumExtensions.svg?label=NuGet)](https://www.nuget.org/packages/FusionReactor.SourceGenerators.EnumExtensions)

# FusionReactor.SourceGenerators.EnumExtensions
A C# source generator to create extensions for an enum type.
- Optimized for speed and low resource consumption
- Support for non-standard enum declarations
```csharp
public enum EPublicFoo : byte
```
- .NET 8+ support by using [FrozenDictionary](https://learn.microsoft.com/en-us/dotnet/api/system.collections.frozen.frozendictionary-2) & [FrozenSet](https://learn.microsoft.com/en-us/dotnet/api/system.collections.frozen.frozenset-1)
- .NET 5+ support by using [IReadOnlyDictionary](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.ireadonlydictionary-2) & [IReadOnlySet](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.ireadonlyset-1)
- .NET Framework 4.5+ support by using [IReadOnlyDictionary](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.ireadonlydictionary-2) & [HashSet](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.hashset-1)

**Package** - [FusionReactor.SourceGenerators.EnumExtensions](https://www.nuget.org/packages/FusionReactor.SourceGenerators.EnumExtensions/)

Add the package to your application using

```bash
dotnet add package FusionReactor.SourceGenerators.EnumExtensions
```

Adding the package will automatically add a marker attribute, `[GenerateEnumExtensions]`, to your project.

To use the generator, add the `[GenerateEnumExtensions]` attribute to an enum. For example:

```csharp
[GenerateEnumExtensions]
[Description("Test 123")]
[IntArray(new[] { 123 })]
[StringArray(new[] { "Foo", "Bar", "Baz" })]
public enum EPublicFoo
{
[Display(
ShortName = "Fo",
Name = "Foo - 0",
Description = "Zero",
Prompt = "ooF",
GroupName = "Foos",
Order = 0)]
Foo = 0,

[Display(
ShortName = "Ba",
Name = "Bar - 1",
Description = "One",
Prompt = "raB",
GroupName = "Bars",
Order = 1)]
Bar = 1,

Batz = 2,
}

```

This will generate a class called `EPublicFooExtensions` (`EPublicFoo` + `Extensions`), which contains a number of helper methods.

`EPublicFoo.Extensions.g.cs`:

```csharp
///
/// Extension methods for the enum.
///
[GeneratedCode("FusionReactor.SourceGenerators.EnumExtensions", null)]
public static class EPublicFooExtensions
{
#if NET8_0_OR_GREATER
private static readonly FrozenDictionary content
= new Dictionary
{
{ EPublicFoo.Foo, 0 },
{ EPublicFoo.Bar, 1 },
{ EPublicFoo.Batz, 2 },
}
.ToFrozenDictionary();
#else
private static readonly Dictionary contentDictionary
= new Dictionary
{
{ EPublicFoo.Foo, 0 },
{ EPublicFoo.Bar, 1 },
{ EPublicFoo.Batz, 2 },
};

private static readonly IReadOnlyDictionary content
= new ReadOnlyDictionary(contentDictionary);
#endif

#if NET8_0_OR_GREATER
private static readonly FrozenSet names
= new HashSet()
{
"Foo",
"Bar",
"Batz",
}
.ToFrozenSet();
#elif NET5_0_OR_GREATER
private static readonly IReadOnlySet names
= new HashSet()
{
"Foo",
"Bar",
"Batz",
};
#else
private static readonly HashSet names
= new HashSet()
{
"Foo",
"Bar",
"Batz",
};
#endif

#if NET8_0_OR_GREATER
private static readonly FrozenSet values
= new HashSet()
{
EPublicFoo.Foo,
EPublicFoo.Bar,
EPublicFoo.Batz,
}
.ToFrozenSet();
#elif NET5_0_OR_GREATER
private static readonly IReadOnlySet names
= new HashSet()
{
EPublicFoo.Foo,
EPublicFoo.Bar,
EPublicFoo.Batz,
};
#else
private static readonly HashSet names
= new HashSet()
{
EPublicFoo.Foo,
EPublicFoo.Bar,
EPublicFoo.Batz,
};
#endif

#if NET8_0_OR_GREATER
private static readonly FrozenSet rootAttributes
= new HashSet()
{
new global::FusionReactor.SourceGenerators.EnumExtensions.GenerateEnumExtensionsAttribute(),
new global::System.ComponentModel.DescriptionAttribute(
"Test 123"),
new global::FusionReactor.SourceGenerators.EnumExtensions.Tests.Attributes.IntArrayAttribute(
new int[]{ 123 }),
new global::FusionReactor.SourceGenerators.EnumExtensions.Tests.Attributes.StringArrayAttribute(
new string[]{ "Foo", "Bar", "Baz" }),
}
.ToFrozenSet();
#elif NET5_0_OR_GREATER
private static readonly IReadOnlySet rootAttributes
= new HashSet()
{
new global::FusionReactor.SourceGenerators.EnumExtensions.GenerateEnumExtensionsAttribute(),
new global::System.ComponentModel.DescriptionAttribute(
"Test 123"),
new global::FusionReactor.SourceGenerators.EnumExtensions.Tests.Attributes.IntArrayAttribute(
new int[]{ 123 }),
new global::FusionReactor.SourceGenerators.EnumExtensions.Tests.Attributes.StringArrayAttribute(
new string[]{ "Foo", "Bar", "Baz" }),
};
#else
private static readonly HashSet rootAttributes
= new HashSet()
{
new global::FusionReactor.SourceGenerators.EnumExtensions.GenerateEnumExtensionsAttribute(),
new global::System.ComponentModel.DescriptionAttribute(
"Test 123"),
new global::FusionReactor.SourceGenerators.EnumExtensions.Tests.Attributes.IntArrayAttribute(
new int[]{ 123 }),
new global::FusionReactor.SourceGenerators.EnumExtensions.Tests.Attributes.StringArrayAttribute(
new string[]{ "Foo", "Bar", "Baz" }),
};
#endif

#if NET8_0_OR_GREATER
private static readonly FrozenDictionary memberAttributes
= new Dictionary()
{
{
EPublicFoo.Foo,
new Attribute[1]
{
new global::System.ComponentModel.DataAnnotations.DisplayAttribute()
{
ShortName = "Fo",
Name = "Foo - 0",
Description = "Zero",
Prompt = "ooF",
GroupName = "Foos",
Order = 0,
},
}
},
{
EPublicFoo.Bar,
new Attribute[1]
{
new global::System.ComponentModel.DataAnnotations.DisplayAttribute()
{
ShortName = "Ba",
Name = "Bar - 1",
Description = "One",
Prompt = "raB",
GroupName = "Bars",
Order = 1,
},
}
},
{
EPublicFoo.Batz,
new Attribute[0]
},
}
.ToFrozenDictionary();
#else
private static readonly Dictionary memberAttributesDictionary
= new Dictionary()
{
{
EPublicFoo.Foo,
new Attribute[1]
{
new global::System.ComponentModel.DataAnnotations.DisplayAttribute()
{
ShortName = "Fo",
Name = "Foo - 0",
Description = "Zero",
Prompt = "ooF",
GroupName = "Foos",
Order = 0,
},
}
},
{
EPublicFoo.Bar,
new Attribute[1]
{
new global::System.ComponentModel.DataAnnotations.DisplayAttribute()
{
ShortName = "Ba",
Name = "Bar - 1",
Description = "One",
Prompt = "raB",
GroupName = "Bars",
Order = 1,
},
}
},
{
EPublicFoo.Batz,
new Attribute[0]
},
};

private static readonly IReadOnlyDictionary memberAttributes
= new ReadOnlyDictionary(memberAttributesDictionary);
#endif

///
/// Gets the content dictionary containing mappings of enum values to values.
///
/// The read-only content dictionary.
#if NET8_0_OR_GREATER
public static FrozenDictionary GetContent()
#else
public static IReadOnlyDictionary GetContent()
#endif
=> content;

///
/// Gets the content dictionary containing mappings of enum values to values.
///
/// The enum value for which to get the content dictionary.
/// The read-only content dictionary.
#if NET8_0_OR_GREATER
public static FrozenDictionary GetContent(this EPublicFoo enumValue)
#else
public static IReadOnlyDictionary GetContent(this EPublicFoo enumValue)
#endif
=> content;

///
/// Retrieves the name of the constant in the .
///
/// The enum value to convert.
///
/// A string containing the name of the ;
/// or if no such constant is found.
///
public static string? GetName(this EPublicFoo enumValue)
=> enumValue switch
{
EPublicFoo.Foo => nameof(EPublicFoo.Foo),
EPublicFoo.Bar => nameof(EPublicFoo.Bar),
EPublicFoo.Batz => nameof(EPublicFoo.Batz),
_ => null,
};

///
/// Retrieves all available names of the .
///
/// An enumerable collection of names.
#if NET8_0_OR_GREATER
public static FrozenSet GetNames()
#elif NET5_0_OR_GREATER
public static IReadOnlySet GetNames()
#else
public static HashSet GetNames()
#endif
=> names;

///
/// Retrieves all available names of the .
///
/// The enumeration value.
/// An enumerable collection of names.
#if NET8_0_OR_GREATER
public static FrozenSet GetNames(this EPublicFoo enumValue)
#elif NET5_0_OR_GREATER
public static IReadOnlySet GetNames(this EPublicFoo enumValue)
#else
public static HashSet GetNames(this EPublicFoo enumValue)
#endif
=> names;

///
/// Retrieves all available values of the .
///
/// An enumerable collection of values.
#if NET8_0_OR_GREATER
public static FrozenSet GetValues()
#elif NET5_0_OR_GREATER
public static IReadOnlySet GetValues()
#else
public static HashSet GetValues()
#endif
=> values;

///
/// Retrieves all available values of the .
///
/// The enumeration value.
/// An enumerable collection of values.
#if NET8_0_OR_GREATER
public static FrozenSet GetValues(this EPublicFoo enumValue)
#elif NET5_0_OR_GREATER
public static IReadOnlySet GetValues(this EPublicFoo enumValue)
#else
public static HashSet GetValues(this EPublicFoo enumValue)
#endif
=> values;

///
/// Parses the specified string representation of the enumeration value to its corresponding
/// value.
///
/// A string containing the name or value to convert.
///
/// A boolean indicating whether to ignore case during the parsing. Default is false.
///
///
/// The value equivalent to the specified string representation.
///
public static EPublicFoo ParseFast(string value, bool ignoreCase = false)
{
if (ignoreCase)
{
return value.ToLowerInvariant() switch
{
"foo" => EPublicFoo.Foo,
"bar" => EPublicFoo.Bar,
"batz" => EPublicFoo.Batz,
_ => throw new ArgumentException(),
};
}
else
{
return value switch
{
"Foo" => EPublicFoo.Foo,
"Bar" => EPublicFoo.Bar,
"Batz" => EPublicFoo.Batz,
_ => throw new ArgumentException(),
};
}
}

///
/// Parses the specified string representation of the enumeration value to its corresponding
/// value.
///
/// The enumeration value.
/// A string containing the name or value to convert.
///
/// A boolean indicating whether to ignore case during the parsing. Default is false.
///
///
/// The value equivalent to the specified string representation.
///
public static EPublicFoo ParseFast(this EPublicFoo enumValue, string value, bool ignoreCase = false)
{
if (ignoreCase)
{
return value.ToLowerInvariant() switch
{
"foo" => EPublicFoo.Foo,
"bar" => EPublicFoo.Bar,
"batz" => EPublicFoo.Batz,
_ => throw new ArgumentException(),
};
}
else
{
return value switch
{
"Foo" => EPublicFoo.Foo,
"Bar" => EPublicFoo.Bar,
"Batz" => EPublicFoo.Batz,
_ => throw new ArgumentException(),
};
}
}

///
/// Tries to parse the specified string representation of an enumeration value to its corresponding
/// enumeration value.
///
/// The string representation of the enumeration value.
///
/// When this method returns, contains the value equivalent
/// to the string representation, if the parse succeeded, or default(EPublicFoo) if the parse failed.
/// true if the parsing was successful; otherwise, false.
public static bool TryParseFast(string value, out EPublicFoo? result)
=> TryParseFast(value, false, out result);

///
/// Tries to parse the specified string representation of an enumeration value to its corresponding
/// enumeration value.
///
/// The value to parse.
///
/// A boolean indicating whether to ignore case during the parsing. Default is false.
///
///
/// When this method returns, contains the value equivalent
/// to the string representation, if the parse succeeded, or null if the parse failed.
///
/// true if the parsing was successful; otherwise, false.
public static bool TryParseFast(string value, bool ignoreCase, out EPublicFoo? result)
{
if (ignoreCase)
{
result = value.ToLowerInvariant() switch
{
"foo" => EPublicFoo.Foo,
"bar" => EPublicFoo.Bar,
"batz" => EPublicFoo.Batz,
_ => null,
};
}
else
{
result = value switch
{
"Foo" => EPublicFoo.Foo,
"Bar" => EPublicFoo.Bar,
"Batz" => EPublicFoo.Batz,
_ => null,
};
}

return result is not null;
}

///
/// Tries to parse the specified string representation of an enumeration value to its corresponding
/// enumeration value.
///
/// The enumeration value.
/// The value to parse.
///
/// When this method returns, contains the value equivalent
/// to the string representation, if the parse succeeded, or null if the parse failed.
///
/// true if the parsing was successful; otherwise, false.
public static bool TryParseFast(this EPublicFoo enumValue, string value, out EPublicFoo? result)
=> enumValue.TryParseFast(value, false, out result);

///
/// Tries to parse the specified string representation of an enumeration value to its corresponding
/// enumeration value.
///
/// The enumeration value.
/// The value to parse.
///
/// A boolean indicating whether to ignore case during the parsing. Default is false.
///
///
/// When this method returns, contains the value equivalent
/// to the string representation, if the parse succeeded, or null if the parse failed.
///
/// true if the parsing was successful; otherwise, false.
public static bool TryParseFast(this EPublicFoo enumValue, string value, bool ignoreCase, out EPublicFoo? result)
{
if (ignoreCase)
{
result = value.ToLowerInvariant() switch
{
"foo" => EPublicFoo.Foo,
"bar" => EPublicFoo.Bar,
"batz" => EPublicFoo.Batz,
_ => null,
};
}
else
{
result = value switch
{
"Foo" => EPublicFoo.Foo,
"Bar" => EPublicFoo.Bar,
"Batz" => EPublicFoo.Batz,
_ => null,
};
}

return result is not null;
}

///
/// Retrieves all available attributes of the .
///
/// An enumerable collection of attributes.
#if NET8_0_OR_GREATER
public static FrozenSet GetRootAttributes()
#elif NET5_0_OR_GREATER
public static IReadOnlySet GetRootAttributes()
#else
public static HashSet GetRootAttributes()
#endif
=> rootAttributes;

///
/// Retrieves all available attributes of the .
///
/// The enumeration value.
/// An enumerable collection of attributes.
#if NET8_0_OR_GREATER
public static FrozenSet GetRootAttributes(this EPublicFoo enumValue)
#elif NET5_0_OR_GREATER
public static IReadOnlySet GetRootAttributes(this EPublicFoo enumValue)
#else
public static HashSet GetRootAttributes(this EPublicFoo enumValue)
#endif
=> rootAttributes;

///
/// Retrieves all available attributes of the .
///
/// An enumerable collection of attributes.
#if NET8_0_OR_GREATER
public static FrozenDictionary GetMemberAttributes()
#else
public static Dictionary GetMemberAttributes()
#endif
=> memberAttributes;

///
/// Retrieves all available attributes of the .
///
/// The enumeration value.
/// An enumerable collection of attributes.
#if NET8_0_OR_GREATER
public static FrozenDictionary GetMemberAttributes(this EPublicFoo enumValue)
#else
public static Dictionary GetMemberAttributes(this EPublicFoo enumValue)
#endif
=> memberAttributes;
}

```

The generated extension files are available in your IDE under the Source Generators files.

## Contributing

Create an [issue](https://github.com/OhFlowi/FusionReactor.SourceGenerators.EnumExtensions/issues/new) if you find a BUG or have a Suggestion or Question. If you want to develop this project :

1. Fork it!
2. Create your feature branch: `git checkout -b my-new-feature`
3. Commit your changes: `git commit -am 'Add some feature'`
4. Push to the branch: `git push origin my-new-feature`
5. Submit a pull request

## License

FusionReactor.SourceGenerators.EnumExtensions is Copyright © 2024 [OhFlowi](https://github.com/OhFlowi) under the MIT License.