-
-
Save anonymous/5f75b33c155c8a114b8e34590cc31aaa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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