Implementation of Linq.Dynamic GroupJoin

.net c# dynamic-linq linq linq-to-objects

Question

I am working on creating an Extension Method in the Linq.Dynamic project for GroupJoin. But, for some reason it will not run. The signatures seem to match.

public static IQueryable GroupJoin(this IQueryable outer, IEnumerable inner, string outerSelector, string innerSelector, string resultsSelector, params object[] values)
{
    if (inner == null) throw new ArgumentNullException("inner");
    if (outerSelector == null) throw new ArgumentNullException("outerSelector");
    if (innerSelector == null) throw new ArgumentNullException("innerSelector");
    if (resultsSelector == null) throw new ArgumentNullException("resultsSelctor");

    LambdaExpression outerSelectorLambda = DynamicExpression.ParseLambda(outer.ElementType, null, outerSelector, values);
    Type enumType = GetList(inner.AsQueryable().ElementType).GetType();

    LambdaExpression innerSelectorLambda = DynamicExpression.ParseLambda(inner.AsQueryable().ElementType, null, innerSelector, values);

    ParameterExpression[] parameters = new ParameterExpression[] { 
    Expression.Parameter(outer.ElementType, "outer"), Expression.Parameter(enumType, "inner") };
    LambdaExpression resultsSelectorLambda = DynamicExpression.ParseLambda(parameters, null, resultsSelector, values);        

    return outer.Provider.CreateQuery(
        Expression.Call(
            typeof(Queryable), "GroupJoin",
            new Type[] { outer.ElementType, inner.AsQueryable().ElementType, outerSelectorLambda.Body.Type, resultsSelectorLambda.Body.Type },
            outer.Expression, inner.AsQueryable().Expression, Expression.Quote(outerSelectorLambda), Expression.Quote(innerSelectorLambda), Expression.Quote(resultsSelectorLambda)));
}

public static IEnumerable GetList(System.Type type)
{
    return (IEnumerable)Activator.CreateInstance(typeof(List<>).MakeGenericType(type));
}

This code gives me the following error:

No generic method 'GroupJoin' on type 'System.Linq.Queryable' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic.

In looking at the results of each piece they seem to match: Writing the follwing GroupJoin:

man.Contacts.GroupJoin(man.ContactAddresses, param_0 => param_0.ContactId, param_0 => param_0.ContactId, 
                (outer, inner) => new { ContactId = outer.ContactId, FirstName = outer.FirstName, LastName = outer.LastName, MI = outer.MiddleInitial, ContactAddresses = inner });

I get the debug of:

.Call System.Linq.Queryable.GroupJoin(
.Constant<IdeaBlade.EntityModel.EntityQueryProxy`1[LOC.AMP.Data.DomainModel.Contact]>(IdeaBlade.EntityModel.EntityQueryProxy`1[LOC.AMP.Data.DomainModel.Contact]),    .Constant<IdeaBlade.EntityModel.EntityQueryProxy`1[LOC.AMP.Data.DomainModel.ContactAddress]>(IdeaBlade.EntityModel.EntityQueryProxy`1[LOC.AMP.Data.DomainModel.ContactAddress]),
'(.Lambda #Lambda1<System.Func`2[LOC.AMP.Data.DomainModel.Contact,System.Int64]>),
'(.Lambda #Lambda2<System.Func`2[LOC.AMP.Data.DomainModel.ContactAddress,System.Int64]>),
'(.Lambda #Lambda3<System.Func`3[LOC.AMP.Data.DomainModel.Contact,System.Collections.Generic.IEnumerable`1[LOC.AMP.Data.DomainModel.ContactAddress],    <>f__AnonymousType0`5[System.Int64,System.String,System.String,System.String,System.Collections.Generic.IEnumerable`1[LOC.AMP.Data.DomainModel.ContactAddress]]]>))
.Lambda #Lambda1<System.Func`2[LOC.AMP.Data.DomainModel.Contact,System.Int64]>(LOC.AMP.Data.DomainModel.Contact $param_0)
{
    $param_0.ContactId
}    
.Lambda #Lambda2<System.Func`2[LOC.AMP.Data.DomainModel.ContactAddress,System.Int64]>(LOC.AMP.Data.DomainModel.ContactAddress $param_0)
{
    $param_0.ContactId
}    
.Lambda 
    #Lambda3<System.Func`3
    [
        LOC.AMP.Data.DomainModel.Contact, System.Collections.Generic.IEnumerable`1[LOC.AMP.Data.DomainModel.ContactAddress],
        <>f__AnonymousType0`5
        [
            System.Int64,System.String,System.String,System.String, System.Collections.Generic.IEnumerable`1
            [
                LOC.AMP.Data.DomainModel.ContactAddress
            ]
        ]
    ]>
    (LOC.AMP.Data.DomainModel.Contact $outer, System.Collections.Generic.IEnumerable`1
        [LOC.AMP.Data.DomainModel.ContactAddress] $inner) 

    {
    .New <>f__AnonymousType0`5[System.Int64,System.String,System.String,System.String,System.Collections.Generic.IEnumerable`1[LOC.AMP.Data.DomainModel.ContactAddress]](
        $outer.ContactId,
        $outer.FirstName,
        $outer.LastName,
        $outer.MiddleInitial,
        $inner)
}

With the following GroupJoin:

man.Contacts.GroupJoin(man.ContactAddresses, "ContactId", "ContactId", "new (outer.ContactId as ContactId, outer.FirstName as FirstName, outer.LastName as LastName, outer.MiddleInitial as MI, inner as ContactAddresses)");

Then looking at the debug:

.Call GroupJoin (
{value(IdeaBlade.EntityModel.EntityQueryProxy'1[LOC.AMP.Data.DomainModel.Contact])},    {value(IdeaBlade.EntityModel.EntityQueryProxy'1[LOC.AMP.Data.DomainModel.ContactAddress])},
'(.Lambda #Lambda1<System.Func'2[LOC.AMP.Data.DomainModel.Contact,System.Int64]>),
'(.Lambda #Lambda1<System.Func'2[LOC.AMP.Data.DomainModel.ContactAddress,System.Int64]>),
'(.Lambda #Lambda1<System.Func'3[LOC.AMP.Data.DomainModel.Contact,System.Collections.Generic.List`1[LOC.AMP.Data.DomainModel.ContactAddress],DynamicClass1]>)

//ContactId
.Lambda #Lambda1<System.Func'2[LOC.AMP.Data.DomainModel.Contact,System.Int64]>(LOC.AMP.Data.DomainModel.Contact $var1) 
{
    $var1.ContactId
}

//CA.ContactId
.Lambda #Lambda1<System.Func'2[LOC.AMP.Data.DomainModel.ContactAddress,System.Int64]>(LOC.AMP.Data.DomainModel.ContactAddress $var1)
{
    $var1.ContactId
}
//Dynamic Result
.Lambda #Lambda1<System.Func`3[LOC.AMP.Data.DomainModel.Contact,System.Collections.Generic.List`1[LOC.AMP.Data.DomainModel.ContactAddress],DynamicClass1]>(
    LOC.AMP.Data.DomainModel.Contact $outer,
    System.Collections.Generic.List`1[LOC.AMP.Data.DomainModel.ContactAddress] $inner)
    {
    .New DynamicClass1(){
        ContactId = $outer.ContactId,
        FirstName = $outer.FirstName,
        LastName = $outer.LastName,
        MI = $outer.MiddleInitial,
        ContactAddresses = $inner
    }
}

The only thing different is List<T> compared to IEnumerable. But List<T> is IEnumerable. The error reads like the signature is wrong. I just can't figure it out.

Any incite would be great.

1
1
3/11/2011 10:58:42 AM

Popular Answer

I know it might be too late but I found this as answer:

Try using:

Type enumType = typeof(IEnumerable<>).MakeGenericType(inner.AsQueryable().ElementType);

It worked for me.

0
10/22/2012 3:36:27 PM


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow