public KeyInfoBase( MemberInfo[] entityKeyMembers, SortOrder[] sortOrders, IComparer <TKey> keyComparer, IKeyInfoHelper helper) { this.entityKeyMembers = entityKeyMembers; if (sortOrders == null) { sortOrders = Enumerable .Repeat(SortOrder.Ascending, helper.GetMemberCount()) .ToArray(); } this.sortOrders = sortOrders; this.keyComparer = keyComparer; this.keySelector = KeyExpressionHelper .CreateKeySelector <TEntity, TKey>(entityKeyMembers, helper) .Compile(); this.keyEmptinessDetector = KeyExpressionHelper .CreateKeyEmptinessDetector <TEntity, TKey>(helper) .Compile(); }
public bool TryCreateKeyInfo <TEntity, TKey>( Expression <Func <TEntity, TKey> > keySelector, out IKeyInfo <TEntity, TKey> result) where TEntity : class { Expression body = keySelector.Body; Type keyType = body.Type; if (!typeof(DataRow).IsAssignableFrom(body.Type)) { result = null; return(false); } IKeyInfoHelper helper = DataRowKeyInfo <TEntity, TKey> .KeyInfoHelper; MemberInfo[] keyMembers; if (!helper.TryParseKeySelectorExpression(keySelector.Body, true, out keyMembers)) { result = null; return(false); } result = new DataRowKeyInfo <TEntity, TKey>(keyMembers); return(true); }
public static Expression CreateKeyConversionExpression( Expression source, MemberInfo[] toMembers, int[] mapping, IKeyInfoHelper from, IKeyInfoHelper to) { int memberCount = mapping.Length; Expression[] factoryArgs = new Expression[memberCount]; for (int i = 0; i < memberCount; i++) { Type requestedType = ReflectionHelper.GetMemberType(toMembers[i]); Expression arg = from.CreateKeyMemberSelectorExpression(source, mapping[i]); if (arg.Type != requestedType) { arg = Expression.Convert(arg, requestedType); } factoryArgs[i] = arg; } return(to.CreateKeyFactoryExpression(factoryArgs)); }
public KeyInfoBase( Expression <Func <TEntity, TKey> > keySelector, SortOrder[] sortOrders, IComparer <TKey> keyComparer, IKeyInfoHelper helper) : this(ParseSelector(keySelector, helper), sortOrders, keyComparer, helper) { }
private static MemberInfo[] ParseSelector( Expression <Func <TEntity, TKey> > selector, IKeyInfoHelper helper) { if (!helper.TryParseKeySelectorExpression( selector.Body, true, out MemberInfo[] result))
public static Expression <Func <TKey, bool> > CreateKeyEmptinessDetector <TEntity, TKey>( IKeyInfoHelper helper) { ParameterExpression param = Expression.Parameter(typeof(TKey)); Expression body = CreateKeyEmptinessDetector(param, helper); return(Expression.Lambda <Func <TKey, bool> >(body, param)); }
public static Expression <Func <TEntity, TKey> > CreateKeySelector <TEntity, TKey>( MemberInfo[] entityMembers, IKeyInfoHelper helper) { ParameterExpression param = Expression.Parameter(typeof(TEntity)); Expression body = CreateKeySelector(param, entityMembers, helper); return(Expression.Lambda <Func <TEntity, TKey> >(body, param)); }
public bool TryCreateKeyInfoHelper(Type keyType, out IKeyInfoHelper result) { if (!typeof(DataRow).IsAssignableFrom(keyType)) { result = null; return(false); } result = new DataRowKeyInfoHelper(keyType); return(true); }
public bool TryCreateKeyInfoHelper( Type keyType, out IKeyInfoHelper result) { if (!ReflectionHelper.IsAnonymousType(keyType)) { result = null; return(false); } result = new AnonymousTypeKeyInfoHelper(keyType); return(true); }
public bool TryCreateKeyInfoHelper( Type keyType, out IKeyInfoHelper result) { if (!ValidateType(keyType)) { result = null; return(false); } result = new PrimitiveKeyInfoHelper(keyType); return(true); }
public bool TryCreateKeyInfo <TEntity, TKey>( Expression <Func <TEntity, TKey> > keySelector, out IKeyInfo <TEntity, TKey> result) where TEntity : class { if (!ValidateType(typeof(TKey))) { result = null; return(false); } IKeyInfoHelper helper = PrimitiveKeyInfo <TEntity, TKey> .KeyInfoHelper; if (!helper.TryParseKeySelectorExpression(keySelector.Body, true, out MemberInfo[] members))
public static Expression CreateKeySelector( Expression source, MemberInfo[] entityMembers, IKeyInfoHelper helper) { Expression[] memberAccess = new Expression[entityMembers.Length]; for (int i = 0; i < entityMembers.Length; i++) { memberAccess[i] = Expression.MakeMemberAccess(source, entityMembers[i]); } Expression body = helper.CreateKeyFactoryExpression(memberAccess); return(body); }
private static MemberInfo[] ParseSelector( Expression <Func <TEntity, TKey> > selector, IKeyInfoHelper helper) { MemberInfo[] result = null; if (!helper.TryParseKeySelectorExpression( selector.Body, true, out result)) { throw new ArgumentException( ExceptionMessages.InvalidKeySelector, "keySelector"); } return(result); }
public bool TryCreateKeyInfoHelper( Type keyType, out IKeyInfoHelper result) { result = null; bool success = false; foreach (IKeyInfoService factory in this.factories) { if (factory.TryCreateKeyInfoHelper(keyType, out result)) { success = true; break; } } return(success); }
private static Func <TFrom, TTo> CreateConversion <TFrom, TTo>( IKeyInfo <TFrom> fromKeyInfo, IKeyInfo <TTo> toKeyInfo, int[] mapping) { IKeyInfoHelper from = GetKeyInfoHelper(fromKeyInfo); IKeyInfoHelper to = GetKeyInfoHelper(toKeyInfo); ParameterExpression keyParam = Expression.Parameter(fromKeyInfo.KeyType); Expression body = KeyExpressionHelper.CreateKeyConversionExpression( keyParam, toKeyInfo.EntityKeyMembers, mapping, from, to); return(Expression.Lambda <Func <TFrom, TTo> >(body, keyParam).Compile()); }
protected override Expression VisitMethodCall(MethodCallExpression node) { if (!node.Method.IsGenericMethod || node.Method.GetGenericMethodDefinition() != this.Original) { // Not GroupJoin return(base.VisitMethodCall(node)); } if (!(node.Arguments[1] is ConstantExpression secondExpression)) { // Not constant expression return(base.VisitMethodCall(node)); } if (!(secondExpression.Value is ITable table)) { // Not table return(base.VisitMethodCall(node)); } LambdaExpression secondKeySelector = ExpressionHelper.SkipQuoteNode(node.Arguments[3]) as LambdaExpression; Type keyType = secondKeySelector.Body.Type; IKeyInfoHelper helper = this.GetKeyInfoHelper(keyType); if (helper == null) { // Cannot detect key type return(base.VisitMethodCall(node)); } // Try to parse expression if (!helper.TryParseKeySelectorExpression( secondKeySelector.Body, false, out MemberInfo[] keyMembers))
public static Expression CreateKeyEmptinessDetector( Expression source, IKeyInfoHelper helper) { Expression body = null; int memberCount = helper.GetMemberCount(); for (int i = 0; i < memberCount; i++) { Expression member = helper.CreateKeyMemberSelectorExpression(source, i); Type memberType = member.Type; if (ReflectionHelper.IsNullable(memberType)) { Expression equalityTest = Expression.Equal( member, Expression.Constant(null, memberType)); if (body == null) { body = equalityTest; } else { body = Expression.Or(body, equalityTest); } } } // If all the members of the anonymous type is not nullable, the body expression // is null at this point if (body == null) { body = Expression.Constant(false); } return(body); }
public bool TryCreateKeyInfo <TEntity, TKey>( Expression <Func <TEntity, TKey> > keySelector, out IKeyInfo <TEntity, TKey> result) where TEntity : class { if (!ReflectionHelper.IsAnonymousType(typeof(TKey))) { result = null; return(false); } IKeyInfoHelper helper = AnonymousTypeKeyInfo <TEntity, TKey> .KeyInfoHelper; MemberInfo[] members; if (!helper.TryParseKeySelectorExpression(keySelector.Body, true, out members)) { result = null; return(false); } result = new AnonymousTypeKeyInfo <TEntity, TKey>(members); return(true); }
protected override Expression VisitMethodCall(MethodCallExpression node) { if (!node.Method.IsGenericMethod || node.Method.GetGenericMethodDefinition() != this.Original) { // Not GroupJoin return(base.VisitMethodCall(node)); } ConstantExpression secondExpression = node.Arguments[1] as ConstantExpression; if (secondExpression == null) { // Not constant expression return(base.VisitMethodCall(node)); } ITable table = secondExpression.Value as ITable; if (table == null) { // Not table return(base.VisitMethodCall(node)); } LambdaExpression secondKeySelector = ExpressionHelper.SkipQuoteNode(node.Arguments[3]) as LambdaExpression; Type keyType = secondKeySelector.Body.Type; IKeyInfoHelper helper = this.GetKeyInfoHelper(keyType); if (helper == null) { // Cannot detect key type return(base.VisitMethodCall(node)); } // Try to parse expression MemberInfo[] keyMembers; if (!helper.TryParseKeySelectorExpression( secondKeySelector.Body, false, out keyMembers)) { // Cannot parse key return(base.VisitMethodCall(node)); } IIndex matchedIndex = null; int[] mapping = null; foreach (IIndex index in table.Indexes) { if (KeyExpressionHelper.TryGetMemberMapping( index.KeyInfo.EntityKeyMembers, keyMembers, out mapping)) { matchedIndex = index; break; } } if (matchedIndex == null) { // No matched index was found return(base.VisitMethodCall(node)); } var indexServices = GetKeyInfoHelper(matchedIndex.KeyInfo); if (indexServices == null) { return(base.VisitMethodCall(node)); } // Create key converter ParameterExpression keyConverterParam = Expression.Parameter(keyType, "x"); LambdaExpression keyConverter = Expression.Lambda( KeyExpressionHelper.CreateKeyConversionExpression(keyConverterParam, matchedIndex.KeyInfo.EntityKeyMembers, mapping, helper, indexServices), keyConverterParam); // Create key emptyness detector ParameterExpression keyEmptinessDetectorParam = Expression.Parameter(keyType, "x"); LambdaExpression keyEmptinessDetector = Expression.Lambda( KeyExpressionHelper.CreateKeyEmptinessDetector( keyEmptinessDetectorParam, helper), keyEmptinessDetectorParam); Type[] generics = node.Method.GetGenericArguments(); // GroupJoinIndexed call MethodInfo indexedMethod = this.Indexed .MakeGenericMethod( generics[0], generics[1], generics[2], matchedIndex.KeyInfo.KeyType, generics[3]); Expression indexedCall = Expression.Call( node.Object, indexedMethod, this.Visit(node.Arguments[0]), Expression.Constant(matchedIndex), ExpressionHelper.SkipQuoteNode(node.Arguments[2]), keyEmptinessDetector, keyConverter, ExpressionHelper.SkipQuoteNode(node.Arguments[4])); Type elementType = ReflectionHelper.GetElementType(indexedCall.Type); // AsQueryable call return(Expression.Call( null, QueryMethods.AsQueryable.MakeGenericMethod(elementType), indexedCall)); }
public GenericKeyComparer(SortOrder[] sortOrders, IKeyInfoHelper helper) { if (helper == null) { throw new ArgumentNullException("helper"); } int memberCount = helper.GetMemberCount(); if (memberCount <= 0) { throw new ArgumentException( ExceptionMessages.InvalidKeyInfoHelper, "helper"); } if (sortOrders == null) { sortOrders = Enumerable.Repeat(SortOrder.Ascending, memberCount).ToArray(); } if (sortOrders.Length != memberCount) { throw new ArgumentException( ExceptionMessages.MemberAndSortOrderCountMismatch, "sortOrders"); } ParameterExpression x = Expression.Parameter(typeof(T), "x"); ParameterExpression y = Expression.Parameter(typeof(T), "y"); ParameterExpression variable = Expression.Variable(typeof(int), "var"); List <Expression> blockBody = new List <Expression>(); for (int i = 0; i < memberCount; i++) { Expression xMember = helper.CreateKeyMemberSelectorExpression(x, i); Expression yMember = helper.CreateKeyMemberSelectorExpression(y, i); Expression expr = Expression.Assign( variable, this.CreateComparsion(xMember, yMember, sortOrders[i])); if (0 < i) { expr = Expression.IfThen( Expression.Equal(variable, Expression.Constant(0)), expr); } blockBody.Add(expr); } // Eval the last variable blockBody.Add(variable); var lambda = Expression.Lambda <Func <T, T, int> >( Expression.Block( new ParameterExpression[] { variable }, blockBody), x, y); this.comparer = lambda.Compile(); }