2011-09-09 13 views
21

私は左の外側の結合を模倣しようとしていますhereしかし、動的linq拡張メソッドを使用します。Dynamic Linqで左外部結合を行うにはどうしたらいいですか?

public static IQueryable SelectMany(this IQueryable source, string selector, 
    string resultsSelector, params object[] values) 
{ 
    if (source == null) throw new ArgumentNullException("source"); 
    if (selector == null) throw new ArgumentNullException("selector"); 

    // Parse the lambda 
    LambdaExpression lambda = DynamicExpression.ParseLambda(
     source.ElementType, null, selector, values); 

    // Fix lambda by recreating to be of correct Func<> type in case 
    // the expression parsed to something other than IEnumerable<T>. 
    // For instance, a expression evaluating to List<T> would result 
    // in a lambda of type Func<T, List<T>> when we need one of type 
    // an Func<T, IEnumerable<T> in order to call SelectMany(). 
    Type inputType = source.Expression.Type.GetGenericArguments()[0]; 
    Type resultType = lambda.Body.Type.GetGenericArguments()[0]; 
    Type enumerableType = typeof(IEnumerable<>).MakeGenericType(resultType); 
    Type delegateType = typeof(Func<,>).MakeGenericType(inputType, 
     enumerableType); 
    lambda = Expression.Lambda(delegateType, lambda.Body, lambda.Parameters); 

    ParameterExpression[] parameters = new ParameterExpression[] { 
     Expression.Parameter(source.ElementType, "outer"), 
     Expression.Parameter(resultType, "inner") 
    }; 

    LambdaExpression resultsSelectorLambda = DynamicExpression.ParseLambda(
     parameters, null, resultsSelector, values); 

    // Create the new query 
    return source.Provider.CreateQuery(Expression.Call(typeof(Queryable), 
     "SelectMany", new Type[] { 
      source.ElementType, 
      resultType, 
      resultsSelectorLambda.Body.Type 
     }, source.Expression, Expression.Quote(lambda), 
     Expression.Quote(resultsSelectorLambda)));    
} 

と::

public static IQueryable GroupJoin(this IQueryable outer, IEnumerable inner, 
    string outerKeySelector, string innerKeySelector, string resultSelector, 
    params object[] values) 
{ 
    Type innerElementType = inner.AsQueryable().ElementType; 

    var outerParameter = Expression.Parameter(outer.ElementType, "outer"); 
    var innerParameter = Expression.Parameter(innerElementType, "inner"); 
    var groupParameter = Expression.Parameter(typeof(IEnumerable<>) 
     .MakeGenericType(innerElementType), "group"); 

    var outerLambda = DynamicExpression.ParseLambda(new[] { outerParameter }, 
     null, outerKeySelector, values); 
    var innerLambda = DynamicExpression.ParseLambda(new[] { innerParameter }, 
     outerLambda.Body.Type, innerKeySelector, values); 
    var resultLambda = DynamicExpression.ParseLambda(new[] { 
     outerParameter, groupParameter }, null, resultSelector, values); 

    return outer.Provider.CreateQuery(Expression.Call(typeof(Queryable), 
     "GroupJoin", new[] { outer.ElementType, innerElementType, 
     outerLambda.Body.Type, resultLambda.Body.Type }, 
     outer.Expression, Expression.Constant(inner), 
     Expression.Quote(outerLambda), Expression.Quote(innerLambda), 
     Expression.Quote(resultLambda))); 
} 

しかし、私はSelectMany

+1

のような呼び出しがありますか? – arviman

答えて

9

DefaultIfEmptyとされて落ちるところ

public static object DefaultIfEmpty(this IQueryable source) 
{ 
    if (source == null) throw new ArgumentNullException("source"); 
     return source.Provider.Execute(
    Expression.Call(
     typeof(Queryable), "DefaultIfEmpty", 
     new Type[] { source.ElementType }, 
     source.Expression)); 
} 
を使用すると void DefaultIfEmpty();

interface IEnumerableSignaturesに追加し、私が持っているもの

は、その後、あなたがここに言及されているDynamicExpressionの実装

var qry = Foo.GroupJoin(Bar, "outer.Id", "inner.Id", "new(outer.Id as Foo, group as Bars)").SelectMany("Bars.DefaultIfEmpty()", "new(outer.Foo as Foo, inner as Bar)"); 
+0

あなたは簡単な情報を教えてくれますか?私はこれを使用する必要があります:( – Licentia

関連する問題