Я решил, что невозможно выполнить следующие (эквивалентные) операции перечисления с помощью отражения - так как класс Enum не имеет операторов, и в выдаваемом коде нет операторов:
object boxedEnum = MyEnum.Flag1 | MyEnum.Flag2;
boxedEnum &= ~MyEnum.Flag2; // Remove the flag.
Итак, я сейчас делаю следующее (эквивалент):
int boxedEnumValue = (int) boxedEnum;
boxedEnumValue &= ~MyEnum.Flag2;
boxedEnum = Enum.ToObject(boxedEnum.GetType(), boxedEnumValue);
Что отлично работает, единственная проблема в том, что эквивалентный код для преобразования boxedEnum в целое число:
int boxedEnumValue = int.Parse(Enum.Format(boxedEnum.GetType(), boxedEnum, "X"), System.Globalization.NumberStyles.HexNumber);
С чем, я уверен, вы согласитесь, это ужасно и смешно.
Итак, у этого вопроса есть два аспекта. Было бы замечательно, если бы кто-то мог доказать, что я не прав, и предоставить средство для выполнения двоичных операций над перечисленными в штучной форме перечислениями - иначе будет полезен любой способ избежать обхода строки.
Гуффа дал мне то, что мне было нужно, чтобы преобразовать перечисление в определенный тип. Я создал метод расширения, который делает все возможное:
/// <summary>
/// Gets the integral value of an enum.
/// </summary>
/// <param name="value">The enum to get the integral value of.</param>
/// <returns></returns>
public static T ToIntegral<T>(this object value)
{
if(object.ReferenceEquals(value, null))
throw new ArgumentNullException("value");
Type rootType = value.GetType();
if (!rootType.IsEnum)
throw new ArgumentOutOfRangeException("value", "value must be a boxed enum.");
Type t = Enum.GetUnderlyingType(rootType);
switch (t.Name.ToUpperInvariant())
{
case "SBYTE":
return (T)Convert.ChangeType((sbyte) value, typeof(T));
case "BYTE":
return (T) Convert.ChangeType((byte) value, typeof(T));
case "INT16":
return (T) Convert.ChangeType((Int16) value, typeof(T));
case "UINT16":
return (T) Convert.ChangeType((UInt16) value, typeof(T));
case "INT32":
return (T) Convert.ChangeType((Int32) value, typeof(T));
case "UINT32":
return (T) Convert.ChangeType((UInt32) value, typeof(T));
case "INT64":
return (T) Convert.ChangeType((Int64) value, typeof(T));
case "UINT64":
return (T) Convert.ChangeType((UInt64) value, typeof(T));
default:
throw new NotSupportedException();
}
}