mirror of
https://github.com/Ellpeck/DynamicEnums.git
synced 2024-11-29 19:48:34 +01:00
Compare commits
No commits in common. "94b6304d52daeba0abe1daba5a395d5cb569bd32" and "1b50b1c48068c263b1de49024a1359871eab16b4" have entirely different histories.
94b6304d52
...
1b50b1c480
3 changed files with 8 additions and 67 deletions
|
@ -13,18 +13,18 @@ namespace DynamicEnums {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A dynamic enum is a class that represents enum-like single-instance value behavior with additional capabilities, including dynamic addition of new arbitrary values.
|
/// A dynamic enum is a class that represents enum-like single-instance value behavior with additional capabilities, including dynamic addition of new arbitrary values.
|
||||||
/// A dynamic enum uses <see cref="BigInteger"/> as its underlying type, allowing for an arbitrary number of enum values to be created, even when a <see cref="FlagsAttribute"/>-like structure is used that would only allow for up to 64 values in a regular enum.
|
/// A dynamic enum uses <see cref="BigInteger"/> as its underlying type, allowing for an arbitrary number of enum values to be created, even when a <see cref="FlagsAttribute"/>-like structure is used that would only allow for up to 64 values in a regular enum.
|
||||||
/// All boolean operations including <see cref="And{T}"/>, <see cref="Or{T}"/>, <see cref="Xor{T}"/> and <see cref="Neg{T}"/> are supported and can be implemented in derived classes using operator overloads.
|
/// All enum operations including <see cref="And{T}"/>, <see cref="Or{T}"/>, <see cref="Xor{T}"/> and <see cref="Neg{T}"/> are supported and can be implemented in derived classes using operator overloads.
|
||||||
/// To create a custom dynamic enum, simply create a class that extends <see cref="DynamicEnum"/>. New values can then be added using <see cref="Add{T}"/>, <see cref="AddValue{T}"/> or <see cref="AddFlag{T}"/>.
|
/// To create a custom dynamic enum, simply create a class that extends <see cref="DynamicEnum"/>. New values can then be added using <see cref="Add{T}"/>, <see cref="AddValue{T}"/> or <see cref="AddFlag{T}"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// To include enum-like operator overloads in a dynamic enum named MyEnum, the following code can be used:
|
/// To include enum-like operator overloads in a dynamic enum named MyEnum, the following code can be used:
|
||||||
/// <code>
|
/// <code>
|
||||||
/// public static implicit operator BigInteger(MyEnum value) => DynamicEnum.GetValue(value);
|
/// public static implicit operator BigInteger(MyEnum value) => GetValue(value);
|
||||||
/// public static implicit operator MyEnum(BigInteger value) => DynamicEnum.GetEnumValue<MyEnum>(value);
|
/// public static implicit operator MyEnum(BigInteger value) => GetEnumValue<MyEnum>(value);
|
||||||
/// public static MyEnum operator |(MyEnum left, MyEnum right) => DynamicEnum.Or(left, right);
|
/// public static MyEnum operator |(MyEnum left, MyEnum right) => Or(left, right);
|
||||||
/// public static MyEnum operator &(MyEnum left, MyEnum right) => DynamicEnum.And(left, right);
|
/// public static MyEnum operator &(MyEnum left, MyEnum right) => And(left, right);
|
||||||
/// public static MyEnum operator ^(MyEnum left, MyEnum right) => DynamicEnum.Xor(left, right);
|
/// public static MyEnum operator ^(MyEnum left, MyEnum right) => Xor(left, right);
|
||||||
/// public static MyEnum operator ~(MyEnum value) => DynamicEnum.Neg(value);
|
/// public static MyEnum operator ~(MyEnum value) => Neg(value);
|
||||||
/// </code>
|
/// </code>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public abstract class DynamicEnum {
|
public abstract class DynamicEnum {
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<RepositoryUrl>https://github.com/Ellpeck/DynamicEnums</RepositoryUrl>
|
<RepositoryUrl>https://github.com/Ellpeck/DynamicEnums</RepositoryUrl>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
<VersionPrefix>1.0.1</VersionPrefix>
|
<VersionPrefix>1.0.0</VersionPrefix>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
59
README.md
59
README.md
|
@ -1,61 +1,2 @@
|
||||||
# DynamicEnums
|
# DynamicEnums
|
||||||
Enum-like single-instance values with additional capabilities, including dynamic addition of new arbitrary values and flags
|
Enum-like single-instance values with additional capabilities, including dynamic addition of new arbitrary values and flags
|
||||||
|
|
||||||
A dynamic enum uses `BigInteger` as its underlying type, allowing for an arbitrary number of enum values to be created, even when a `Flags`-like structure is used that would only allow for up to 64 values in a regular enum. All boolean operations including `And<T>(T, T)`, `Or<T>(T, T)`, `Xor<T>(T, T)` and `Neg<T>(T)` are supported and can be implemented in derived classes using operator overloads.
|
|
||||||
|
|
||||||
## Setting it up
|
|
||||||
To create a custom dynamic enum, simply create a class that extends `DynamicEnum`. New values can then be added using `Add<T>(string, BigInteger)`, `AddValue<T>(string)` or `AddFlag<T>(string)`. In this example, they are added as static values in the class itself, but they can be added from anywhere.
|
|
||||||
|
|
||||||
```cs
|
|
||||||
public class MyEnum : DynamicEnum {
|
|
||||||
|
|
||||||
// adding specifically defined values
|
|
||||||
public static readonly MyEnum ValueOne = DynamicEnum.Add<MyEnum>("ValueOne", 1);
|
|
||||||
public static readonly MyEnum ValueTwo = DynamicEnum.Add<MyEnum>("ValueTwo", 2);
|
|
||||||
public static readonly MyEnum ValueThree = DynamicEnum.Add<MyEnum>("ValueThree", 3);
|
|
||||||
|
|
||||||
// adding flags, which automatically uses the next available power of two as its value
|
|
||||||
public static readonly MyEnum FlagOne = DynamicEnum.AddFlag<MyEnum>("FlagOne");
|
|
||||||
public static readonly MyEnum FlagTwo = DynamicEnum.AddFlag<MyEnum>("FlagTwo");
|
|
||||||
public static readonly MyEnum FlagThree = DynamicEnum.AddFlag<MyEnum>("FlagThree");
|
|
||||||
|
|
||||||
// this constructor is called internally using reflection
|
|
||||||
public MyEnum(string name, BigInteger value) : base(name, value) {}
|
|
||||||
|
|
||||||
// you can optionally create operator overloads for easier operations
|
|
||||||
public static implicit operator BigInteger(MyEnum value) => DynamicEnum.GetValue(value);
|
|
||||||
public static implicit operator MyEnum(BigInteger value) => DynamicEnum.GetEnumValue<MyEnum>(value);
|
|
||||||
public static MyEnum operator |(MyEnum left, MyEnum right) => DynamicEnum.Or(left, right);
|
|
||||||
public static MyEnum operator &(MyEnum left, MyEnum right) => DynamicEnum.And(left, right);
|
|
||||||
public static MyEnum operator ^(MyEnum left, MyEnum right) => DynamicEnum.Xor(left, right);
|
|
||||||
public static MyEnum operator ~(MyEnum value) => DynamicEnum.Neg(value);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Using it
|
|
||||||
Dynamic enums work very similarly to regular enums in how you use them, and each operation us optimized through an internal cache. Here are some examples of interactions with the dynamic enum we created above.
|
|
||||||
|
|
||||||
```cs
|
|
||||||
// getting the underlying value
|
|
||||||
BigInteger val1 = DynamicEnum.GetValue(MyEnum.FlagTwo); // using GetValue
|
|
||||||
BigInteger val2 = (BigInteger) MyEnum.FlagTwo; // using our operator overloads
|
|
||||||
|
|
||||||
// creating a combined flag
|
|
||||||
MyEnum allFlags1 = DynamicEnum.Or(MyEnum.FlagOne, DynamicEnum.Or(MyEnum.FlagTwo, MyEnum.FlagThree)); // using Or
|
|
||||||
MyEnum allFlags2 = MyEnum.FlagOne | MyEnum.FlagTwo | MyEnum.FlagThree; // using our operator overloads
|
|
||||||
MyEnum mixedFlags = DynamicEnum.Or(MyEnum.FlagOne, DynamicEnum.GetEnumValue<MyEnum>(17)); // using non-defined values in our combined flags
|
|
||||||
|
|
||||||
// querying flag information
|
|
||||||
bool hasAny = allFlags1.HasAnyFlags(MyEnum.FlagOne | MyEnum.ValueOne); // true
|
|
||||||
bool hasAll = allFlags1.HasAllFlags(MyEnum.FlagOne | MyEnum.ValueOne); // false
|
|
||||||
|
|
||||||
// displaying a dynamic enum value or flag
|
|
||||||
Console.WriteLine(MyEnum.FlagOne); // "FlagOne"
|
|
||||||
Console.WriteLine(allFlags1); // "FlagOne | FlagTwo | FlagThree"
|
|
||||||
|
|
||||||
// parsing a dynamic enum value
|
|
||||||
MyEnum parsed1 = DynamicEnum.Parse<MyEnum>("FlagOne");
|
|
||||||
MyEnum parsed2 = DynamicEnum.Parse<MyEnum>("FlagOne | FlagThree");
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also check out [the tests](https://github.com/Ellpeck/DynamicEnums/tree/main/Tests) for some more complex examples.
|
|
Loading…
Reference in a new issue