/// <summary> /// Returns the expression that compares two IDictionary members /// </summary> /// <param name="ctx"></param> /// <param name="engine"></param> /// <param name="memberType"></param> /// <returns></returns> private static MethodCallExpression GetIDictionaryMemberExpression(Context ctx, IComparerEngine engine, Type memberType) { var nullChecked = new NullChecked(ctx, memberType); var genericPropTypes = memberType.GetGenericArguments(); var methodInfo = CollectionComparer.GetCompareIDictionaryMethodInfo(genericPropTypes); if (IsSimpleType(genericPropTypes[1])) { return(Expression.Call(ctx.List, _listAddRange, Expression.Call( methodInfo, Expression.Constant(ctx.Name), nullChecked.PropA, nullChecked.PropB))); } return(Expression.Call(ctx.List, _listAddRange, Expression.Call( methodInfo, Expression.Constant(engine), Expression.Constant(ctx.Name), nullChecked.PropA, nullChecked.PropB))); }
/// <summary> /// Returns the expression that compares two IEnumerable members /// </summary> /// <param name="ctx"></param> /// <param name="engine"></param> /// <param name="configuration"></param> /// <param name="memberType"></param> /// <returns></returns> private static Expression GetIEnumerableMemberExpression(Context ctx, IComparerEngine engine, EnumerableConfiguration configuration, Type memberType) { var nullChecked = new NullChecked(ctx, memberType); if (configuration != null && !string.IsNullOrEmpty(configuration.Match)) { var itemType = memberType.IsArray ? memberType.GetElementType() : GetGenericIEnumerableType(memberType).First(); var types = new[] { itemType, configuration.MatcherType }; // Static call to CollectionComparer.CompareIEnumerableWithKeyAndDefault<T, TKey> to compare IEnumerable properties return(Expression.Call(ctx.List, _listAddRange, Expression.Call(CollectionComparer.GetCompareIEnumerableWithKeyAndDefaultMethodInfo(types), Expression.Constant(engine), Expression.Constant(ctx.Name), nullChecked.PropA, nullChecked.PropB, configuration.Matcher, Expression.Convert( Expression.Constant(configuration.DefaultId), configuration.MatcherType)))); } // Static call to CollectionComparer.CompareIEnumerable<T> to compare IEnumerable properties return(Expression.Call(ctx.List, _listAddRange, Expression.Call(CollectionComparer.GetCompareIEnumerableMethodInfo(GetGenericIEnumerableType(memberType)), Expression.Constant(ctx.Name), nullChecked.PropA, nullChecked.PropB))); }
/// <summary> /// Generates the Expression Tree required to test for null and then /// recursively test a nested object in the current object /// </summary> /// <param name="type"></param> /// <param name="ctx"></param> /// <param name="memberType"></param> /// <param name="configuration"></param> /// <param name="hierarchy"></param> /// <returns></returns> private static Expression GetSafeguardedRecursiveExpression(Type type, Context ctx, Type memberType, ComparerConfiguration configuration, HashSet <Type> hierarchy) { var tempA = Expression.Parameter(memberType, "tempA"); var tempB = Expression.Parameter(memberType, "tempB"); var nullChecked = new NullChecked(ctx, memberType); var blockExpressions = new List <Expression>() { Expression.Assign(tempA, nullChecked.PropA), Expression.Assign(tempB, nullChecked.PropB), }; var recursiveCtx = new Context() { ObjectA = tempA, ObjectB = tempB, Name = ctx.Name, List = ctx.List, }; var expression = GetExpressionsForType(type, recursiveCtx, configuration, hierarchy); if (expression != null) { blockExpressions.Add(expression); } return(Expression.Block( new[] { tempA, tempB }, blockExpressions )); }