public void ExtractSingleMemberSucceedsWhenOneMemberExistsTest() { Expression <Func <TestClass, int> > expr = p => p.Id; var memberExpression = MemberExtractor.ExtractSingleMember(expr); Assert.AreEqual(memberExpression.Member, typeof(TestClass).GetProperty(nameof(TestClass.Id))); }
public static IEnumerable <T> SetReferences <T, V, U>( this IEnumerable <T> source, Expression <Func <T, V> > property, IEnumerable <U> target, Expression <Func <T, U, bool> > joinExpression, KeyBuilder keyBuilder) where V : IEnumerable <U> { if (source == null || target == null) { return(source); } var member = MemberExtractor.ExtractSingleMember(property); var setter = typeof(T).CreateCollectionPropertySetter <T, U>(member.Member.Name, member.Type); var collection = source as ICollection <T> ?? source.ToList(); //TODO see if this can be cached? Expression <Func <U, T, bool> > reverseJoin = Expression.Lambda <Func <U, T, bool> >(joinExpression.Body, joinExpression.Parameters[1], joinExpression.Parameters[0]); var targetLookup = target.ToExpressionKeyLookup(reverseJoin); var ifnullSetter = typeof(T).CreatePropertySetup <T, U>(member.Member.Name); if (targetLookup != null) { foreach (var parentEntity in collection) { var existingChildEntities = ifnullSetter(parentEntity); var childEntities = new HashSet <U>( targetLookup.GetMatches(parentEntity), keyBuilder.GetKeyComparer <U>()); childEntities.ExceptWith(existingChildEntities); foreach (var childEntity in childEntities) { setter(parentEntity, childEntity); } } return(collection); } var func = joinExpression.Compile(); foreach (var childItem in collection) { ifnullSetter(childItem); foreach (var matchingParent in target.Where(x => func(childItem, x))) { setter(childItem, matchingParent); } } return(collection); }
protected void AddRelationship <TEntity, TOther>(Expression <Func <TEntity, TOther> > memberExpr, Expression <Func <TEntity, TOther, bool> > relationshipExpr) { var relationship = new Relationship( MemberExtractor.ExtractSingleMember(memberExpr).Member, memberExpr, relationshipExpr); var store = RelationshipsStore.AddOrUpdate(typeof(TEntity), new TypeRelationships(typeof(TEntity), typeof(TEntity).GetRealBaseType(), relationship), (_, tr) => new TypeRelationships(tr, relationship)); UpdateTypeHierachies(store.BaseType, store.Type); }
public void ExtractSingleMemberFailWhenMulitpleMembersExistTest() { bool exceptionThrown = false; Expression <Func <TestClass, int> > expr = p => p.Id + p.ParentId.Value; try { MemberExtractor.ExtractSingleMember(expr); } catch (InvalidOperationException) { exceptionThrown = true; } Assert.IsTrue(exceptionThrown); }
public void ExtractSingleMemberFailWhenNoMembersExistTest() { bool exceptionThrown = false; Expression <Func <TestClass, int> > expr = p => 12; try { MemberExtractor.ExtractSingleMember(expr); } catch (ArgumentNullException) { exceptionThrown = true; } Assert.IsTrue(exceptionThrown); }
private static Func <T, int> CreateHashCode <T>(IEnumerable <LambdaExpression> keys) { var param = Expression.Parameter(typeof(T), "source"); var hasher = Expression.New(typeof(HashCode)); var hasherVariable = Expression.Variable(typeof(HashCode), "h"); var assign = Expression.Assign(hasherVariable, hasher); var expressions = new List <Expression> { hasherVariable, assign }; foreach (var key in keys) { var exprWithNewParam = ParameterReplacer.Replace(key, key.Parameters.First(), param) as LambdaExpression; var memberExpr = MemberExtractor.ExtractSingleMember(exprWithNewParam.Body); var memberType = memberExpr.Member.GetMemberUnderlyingType(); var hashCodeAdd = Expression.Call(hasherVariable, nameof(HashCode.Add), new Type[] { key.ReturnType }, exprWithNewParam.Body); if (memberType.IsNullable()) { var isNull = Expression.NotEqual(memberExpr, Expression.Constant(null, memberType)); var @if = Expression.IfThen(isNull, hashCodeAdd); expressions.Add(@if); } else { expressions.Add(hashCodeAdd); } } var returnTarget = Expression.Label(typeof(int)); expressions.Add(Expression.Return(returnTarget, Expression.Call(hasherVariable, typeof(HashCode).GetMethod(nameof(HashCode.ToHashCode))), typeof(int))); expressions.Add(Expression.Label(returnTarget, Expression.Constant(default(int)))); var block = Expression.Block(new[] { hasherVariable }, expressions); var lambda = Expression.Lambda <Func <T, int> >(block, param); return(lambda.Compile()); }
public static IEnumerable <T> SetReferences <T, U>( this IEnumerable <T> source, Expression <Func <T, U> > property, IEnumerable <U> target, Expression <Func <T, U, bool> > joinExpression) { if (source == null || target == null) { return(source); } var member = MemberExtractor.ExtractSingleMember(property); var setter = property.Parameters[0].Type.CreatePropertySetter <T, U>(member.Member.Name); var collection = source as ICollection <T> ?? source.ToList(); var lookup = collection.ToExpressionKeyLookup(joinExpression); if (lookup != null) { foreach (var parentItem in target) { foreach (var matchingChild in lookup.GetMatches(parentItem)) { //set item to match.property setter(matchingChild, parentItem); } } } //fallback to looping through when no hashCode key can be created else { var func = joinExpression.Compile(); foreach (var childItem in source) { var matchingParent = target.FirstOrDefault(x => func(childItem, x)); setter(childItem, matchingParent); } } return(collection); }