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); }
private static MemberInfo[] ParseSelector( Expression <Func <TEntity, TKey> > selector, IKeyInfoHelper helper) { if (!helper.TryParseKeySelectorExpression( selector.Body, true, out MemberInfo[] result))
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))
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); }
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 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)); }