mirror of
https://github.com/Ellpeck/DynamicEnums.git
synced 2024-11-12 21:09:09 +01:00
allow dynamic enum classes to use a parameterless constructor
This commit is contained in:
parent
94d12cdc5d
commit
e17ebf9973
3 changed files with 29 additions and 8 deletions
|
@ -30,13 +30,22 @@ namespace DynamicEnums {
|
|||
/// </remarks>
|
||||
public abstract class DynamicEnum {
|
||||
|
||||
private const BindingFlags ConstructorFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||
private static readonly Type[] ConstructorTypes = {typeof(string), typeof(BigInteger), typeof(bool)};
|
||||
private static readonly Dictionary<Type, Storage> Storages = new Dictionary<Type, Storage>();
|
||||
private readonly BigInteger value;
|
||||
|
||||
private Dictionary<DynamicEnum, bool> allFlagsCache;
|
||||
private Dictionary<DynamicEnum, bool> anyFlagsCache;
|
||||
private BigInteger value;
|
||||
private string name;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new dynamic enum instance.
|
||||
/// This constructor is protected as it is only invoked via reflection.
|
||||
/// This constructor is only called if the class doesn't have the <see cref="DynamicEnum(string,BigInteger,bool)"/> constructor.
|
||||
/// </summary>
|
||||
protected DynamicEnum() {}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new dynamic enum instance.
|
||||
/// This constructor is protected as it is only invoked via reflection.
|
||||
|
@ -45,8 +54,8 @@ namespace DynamicEnums {
|
|||
/// <param name="value">The value</param>
|
||||
/// <param name="defined">Whether this enum value <see cref="IsDefined(DynamicEnum)"/>, and thus, not a combined flag.</param>
|
||||
protected DynamicEnum(string name, BigInteger value, bool defined) {
|
||||
this.value = value;
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -445,7 +454,17 @@ namespace DynamicEnums {
|
|||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
|
||||
#endif
|
||||
Type type, string name, BigInteger value, bool defined) {
|
||||
return (DynamicEnum) Activator.CreateInstance(type, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new object[] {name, value, defined}, CultureInfo.InvariantCulture);
|
||||
// try to call the constructor with parameters first
|
||||
var parameterConstructor = type.GetConstructor(DynamicEnum.ConstructorFlags, null, DynamicEnum.ConstructorTypes, null);
|
||||
if (parameterConstructor != null)
|
||||
return (DynamicEnum) parameterConstructor.Invoke(DynamicEnum.ConstructorFlags, null, new object[] {name, value, defined}, CultureInfo.InvariantCulture);
|
||||
|
||||
// default to the empty constructor and set the values manually
|
||||
var emptyConstructor = type.GetConstructor(DynamicEnum.ConstructorFlags, null, Type.EmptyTypes, null);
|
||||
var ret = (DynamicEnum) emptyConstructor.Invoke(DynamicEnum.ConstructorFlags, null, null, CultureInfo.InvariantCulture);
|
||||
ret.name = name;
|
||||
ret.value = value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private class Storage {
|
||||
|
|
|
@ -19,9 +19,6 @@ public class MyEnum : DynamicEnum {
|
|||
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);
|
||||
|
|
|
@ -35,6 +35,9 @@ public class EnumTests {
|
|||
var zero = DynamicEnum.Add<TestDynamicEnum>("Zero", 0);
|
||||
var combined = DynamicEnum.Add<TestDynamicEnum>("Combined", DynamicEnum.GetValue(DynamicEnum.Or(flags[7], flags[13])));
|
||||
|
||||
DynamicEnum.Add<TestEnumWithConstructor>("Test", 10);
|
||||
Assert.AreEqual(DynamicEnum.GetEnumValue<TestEnumWithConstructor>(10).ToString(), "TestModified");
|
||||
|
||||
Assert.AreEqual(DynamicEnum.GetValue(flags[7]), BigInteger.One << 7);
|
||||
Assert.AreEqual(DynamicEnum.GetEnumValue<TestDynamicEnum>(BigInteger.One << 75), flags[75]);
|
||||
|
||||
|
@ -90,9 +93,11 @@ public class EnumTests {
|
|||
|
||||
}
|
||||
|
||||
private class TestDynamicEnum : DynamicEnum {
|
||||
private class TestDynamicEnum : DynamicEnum;
|
||||
|
||||
public TestDynamicEnum(string name, BigInteger value, bool defined) : base(name, value, defined) {}
|
||||
private class TestEnumWithConstructor : DynamicEnum {
|
||||
|
||||
public TestEnumWithConstructor(string name, BigInteger value, bool defined) : base($"{name}Modified", value, defined) {}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue