Last active
August 29, 2015 14:17
-
-
Save csuzw/9c027eed741db0f137f0 to your computer and use it in GitHub Desktop.
MemberInfo for non-Member expressions
This file contains hidden or 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
/// <summary> | |
/// Crude but effective for my requirements. | |
/// </summary> | |
public class ExpressionMemberInfo<T, TProperty> : MemberInfo | |
{ | |
private static readonly Dictionary<ExpressionType, string> _operatorDescriptions = new Dictionary<ExpressionType, string> | |
{ | |
{ ExpressionType.Add, "+" }, | |
{ ExpressionType.AddAssign, "+" }, | |
{ ExpressionType.AddAssignChecked, "+" }, | |
{ ExpressionType.AddChecked, "+" }, | |
{ ExpressionType.And, "&" }, | |
{ ExpressionType.AndAlso, "&&" }, | |
{ ExpressionType.AndAssign, "&" }, | |
{ ExpressionType.Decrement, "-" }, | |
{ ExpressionType.Divide, "/" }, | |
{ ExpressionType.DivideAssign, "/" }, | |
{ ExpressionType.ExclusiveOr, "^" }, | |
{ ExpressionType.ExclusiveOrAssign, "^" }, | |
{ ExpressionType.GreaterThan, ">" }, | |
{ ExpressionType.GreaterThanOrEqual, ">=" }, | |
{ ExpressionType.Increment, "+" }, | |
{ ExpressionType.LeftShift, "<<" }, | |
{ ExpressionType.LeftShiftAssign, "<<" }, | |
{ ExpressionType.LessThan, "<" }, | |
{ ExpressionType.LessThanOrEqual, "<=" }, | |
{ ExpressionType.Modulo, "%" }, | |
{ ExpressionType.ModuloAssign, "%" }, | |
{ ExpressionType.Multiply, "*" }, | |
{ ExpressionType.MultiplyAssign, "*" }, | |
{ ExpressionType.MultiplyAssignChecked, "*" }, | |
{ ExpressionType.MultiplyChecked, "*" }, | |
{ ExpressionType.Not, "!" }, | |
{ ExpressionType.NotEqual, "!" }, | |
{ ExpressionType.OnesComplement, "~" }, | |
{ ExpressionType.Or, "|" }, | |
{ ExpressionType.OrAssign, "|" }, | |
{ ExpressionType.OrElse, "||" }, | |
{ ExpressionType.PostDecrementAssign, "-" }, | |
{ ExpressionType.PostIncrementAssign, "+" }, | |
{ ExpressionType.Power, "^" }, | |
{ ExpressionType.PowerAssign, "^" }, | |
{ ExpressionType.PreDecrementAssign, "-" }, | |
{ ExpressionType.PreIncrementAssign, "+" }, | |
{ ExpressionType.RightShift, ">>" }, | |
{ ExpressionType.RightShiftAssign, ">>" }, | |
{ ExpressionType.Subtract, "-" }, | |
{ ExpressionType.SubtractAssign, "-" }, | |
{ ExpressionType.SubtractAssignChecked, "-" }, | |
{ ExpressionType.SubtractChecked, "-" }, | |
{ ExpressionType.UnaryPlus, "+" } | |
}; | |
private readonly Lazy<string> _name; | |
public ExpressionMemberInfo(Expression<Func<T, TProperty>> expression) | |
{ | |
_name = new Lazy<string>(() => GetName(expression)); | |
} | |
public override Type DeclaringType | |
{ | |
get { return typeof(T); } | |
} | |
public override MemberTypes MemberType | |
{ | |
get { return MemberTypes.Custom; } | |
} | |
public override string Name | |
{ | |
get { return _name.Value; } | |
} | |
public override Type ReflectedType | |
{ | |
get { return typeof(T); } | |
} | |
public override object[] GetCustomAttributes(Type attributeType, bool inherit) | |
{ | |
return null; | |
} | |
public override object[] GetCustomAttributes(bool inherit) | |
{ | |
return null; | |
} | |
public override bool IsDefined(Type attributeType, bool inherit) | |
{ | |
return false; | |
} | |
private string GetName(Expression<Func<T, TProperty>> expression) | |
{ | |
//return expression.Body.ToString(); // this returns information we don't want to display to an end user | |
var members = GetMembers(expression.Body); | |
var stringBuilder = new StringBuilder(); | |
var first = true; | |
foreach (var member in members) | |
{ | |
if (first) | |
{ | |
stringBuilder.Append(member.Expression.Member.Name); | |
first = false; | |
continue; | |
} | |
stringBuilder.AppendFormat(" {0} {1}", GetOperatorDescription(member.Operator), member.Expression.Member.Name); | |
} | |
return stringBuilder.ToString(); | |
} | |
private string GetOperatorDescription(ExpressionType? operatorType) | |
{ | |
return (operatorType != null && _operatorDescriptions.ContainsKey(operatorType.Value)) | |
? _operatorDescriptions[operatorType.Value] | |
: ","; | |
} | |
private IEnumerable<Member> GetMembers(Expression toUnwrap, ExpressionType? type = null) | |
{ | |
var memberExp = toUnwrap as MemberExpression; | |
if (memberExp != null) yield return new Member { Expression = memberExp, Operator = type }; | |
var unaryExp = toUnwrap as UnaryExpression; | |
if (unaryExp != null) | |
{ | |
foreach (var member in GetMembers(unaryExp.Operand, unaryExp.NodeType)) | |
{ | |
yield return member; | |
} | |
} | |
var binaryExp = toUnwrap as BinaryExpression; | |
if (binaryExp != null) | |
{ | |
foreach (var member in GetMembers(binaryExp.Left, type)) | |
{ | |
yield return member; | |
} | |
foreach (var member in GetMembers(binaryExp.Right, binaryExp.NodeType)) | |
{ | |
yield return member; | |
} | |
} | |
} | |
private class Member | |
{ | |
public MemberExpression Expression { get; set; } | |
public ExpressionType? Operator { get; set; } | |
} | |
} |
This file contains hidden or 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
/// <summary> | |
/// FluentValidation extension methods that make use of my custom MemberInfo for expressions. | |
/// </summary> | |
public static IRuleBuilderOptions<T, TProperty> GreaterThan<T, TProperty>(this IRuleBuilder<T, TProperty> ruleBuilder, Expression<Func<T, TProperty>> expression) | |
{ | |
return ruleBuilder.SetValidator(new GreaterThanValidator(expression.Compile().CoerceToNonGeneric(), new ExpressionMemberInfo<T, TProperty>(expression))); | |
} | |
public static IRuleBuilderOptions<T, TProperty> GreaterThanOrEqual<T, TProperty>(this IRuleBuilder<T, TProperty> ruleBuilder, Expression<Func<T, TProperty>> expression) | |
{ | |
return ruleBuilder.SetValidator(new GreaterThanOrEqualValidator(expression.Compile().CoerceToNonGeneric(), new ExpressionMemberInfo<T, TProperty>(expression))); | |
} | |
public static IRuleBuilderOptions<T, TProperty> LessThan<T, TProperty>(this IRuleBuilder<T, TProperty> ruleBuilder, Expression<Func<T, TProperty>> expression) | |
{ | |
return ruleBuilder.SetValidator(new LessThanValidator(expression.Compile().CoerceToNonGeneric(), new ExpressionMemberInfo<T, TProperty>(expression))); | |
} | |
public static IRuleBuilderOptions<T, TProperty> LessThanOrEqual<T, TProperty>(this IRuleBuilder<T, TProperty> ruleBuilder, Expression<Func<T, TProperty>> expression) | |
{ | |
return ruleBuilder.SetValidator(new LessThanOrEqualValidator(expression.Compile().CoerceToNonGeneric(), new ExpressionMemberInfo<T, TProperty>(expression))); | |
} | |
public static IRuleBuilderOptions<T, TProperty> Equal<T, TProperty>(this IRuleBuilder<T, TProperty> ruleBuilder, Expression<Func<T, TProperty>> expression) | |
{ | |
return ruleBuilder.SetValidator(new EqualValidator(expression.Compile().CoerceToNonGeneric(), new ExpressionMemberInfo<T, TProperty>(expression))); | |
} | |
public static IRuleBuilderOptions<T, TProperty> NotEqual<T, TProperty>(this IRuleBuilder<T, TProperty> ruleBuilder, Expression<Func<T, TProperty>> expression) | |
{ | |
return ruleBuilder.SetValidator(new NotEqualValidator(expression.Compile().CoerceToNonGeneric(), new ExpressionMemberInfo<T, TProperty>(expression))); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment