Skip to content

Instantly share code, notes, and snippets.

/Horrible.cs Secret

Created July 19, 2016 19:21
Show Gist options
  • Save anonymous/5f75b33c155c8a114b8e34590cc31aaa to your computer and use it in GitHub Desktop.
Save anonymous/5f75b33c155c8a114b8e34590cc31aaa to your computer and use it in GitHub Desktop.
private static readonly MethodInfo ConvertFromEnum = typeof(Convert).GetMethod("ChangeType", new[] {typeof(object), typeof(Type)}); // ChangeType is always the same, so we can get it once
// Dynamically construct an expression that is either "value | flag" or "value & ~flag", where "value" and "flag" are of the enum's underlying type
private static EnumMerge Build(Type enumType, Func<Expression, Expression, Expression> bitwise)
{
// declare input parameters
var valueParam = Expression.Parameter(typeof(Enum), "value");
var flagParam = Expression.Parameter(typeof(Enum), "flag");
// call ChangeType and cast to underlying type
var underlyingType = Enum.GetUnderlyingType(enumType);
var convertValue = Expression.Convert(Expression.Call(ConvertFromEnum, valueParam, Expression.Constant(underlyingType)), underlyingType); // (underlying)Convert.ChangeType(value, underlyingType)
var convertFlag = Expression.Convert(Expression.Call(ConvertFromEnum, flagParam, Expression.Constant(underlyingType)), underlyingType); // (underlying)Convert.ChangeType(flag, underlyingType)
// the bitwise operation
var result = bitwise(convertValue, convertFlag);
// call ToObject and cast to Enum
var method = typeof(Enum).GetMethod("ToObject", new[] {typeof (Type), underlyingType});
var resultValue = Expression.Call(method, Expression.Constant(enumType), result); // we select the right ToObject overload based on the underlying type
var resultValueConvert = Expression.Convert(resultValue, typeof(Enum));
// Compile to a lambda for faster execution (i.e. this is not dynamic invoke)
return Expression.Lambda<EnumMerge>(resultValueConvert, valueParam, flagParam).Compile();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment