How can I use Linq on an ITypedList?

c# dynamic-linq linq

Question

So far, I've discovered that Linq can be used on real, as opposed to virtual, class fields and attributes. ITypedList cannot be used with Linq, not even dynamic Linq, in other words.

I tested the below code:

    IQueryable contact ; ...

    dynamic l = contact.Select("Customer.Name as Name"); 
   // Customer is a virtual property provided by the interface of ITypedList.

The error that said "No linkedPropertyName or field "Customer" exists in type "Contact"" was the next thing I encountered.

I looked into dynamic Linq and discovered the code that caused the exception to be raised:

            MemberInfo member = FindPropertyOrField(type, id, instance == null);
            if (member == null)
                throw ParseError(errorPos, Res.UnknownPropertyOrField,
                    id, GetTypeName(type));
            return member is PropertyInfo ?
                Expression.Property(instance, (PropertyInfo)member) :
                Expression.Field(instance, (FieldInfo)member);

in the Expression ParseMemberAccess method (Type type, Expression instance).

It is clear that Linq only supports actual members of fields and properties.

However, I still believe that someone has managed to perform Linq on virtual properties.

If you are able to, please share your experience.

I'm grateful in advance.

Ying

1
4
8/5/2010 6:27:49 PM

Popular Answer

Although it isn't significantly better than code written without linq expressions, the following code is nonetheless shown.

The ITypedList in your code is assumed to be an IList. Obtains a property descriptor for the requested property and performs a for(int I = 0; i((ICollection)list) test on each item in the collection. Count;i++) {\s...\s}

        ParameterExpression listParameter = Expression.Parameter(
            typeof(ITypedList),
            "list"
        );
        ParameterExpression propertyDescriptorVariable = Expression.Variable(
            typeof(PropertyDescriptor),
            "propertyDescriptor"
        );
        ParameterExpression indexVariable = Expression.Variable(
            typeof(int),
            "index"
        );
        ParameterExpression resultVariable = Expression.Variable(
            typeof(bool),
            "result"
        );
        LabelTarget @break = Expression.Label();
        Expression<Func<ITypedList, bool>> lambdaExpression = Expression.Lambda<Func<ITypedList, bool>>(
            Expression.Block(
                new[] { propertyDescriptorVariable, indexVariable, resultVariable },
                Expression.Assign(
                    propertyDescriptorVariable,
                    Expression.Property(
                        Expression.Call(
                            listParameter,
                            typeof(ITypedList).GetMethod(
                                "GetItemProperties",
                                BindingFlags.Instance | BindingFlags.Public
                            ),
                            Expression.Default(
                                typeof(PropertyDescriptor[])
                            )
                        ),
                        typeof(PropertyDescriptorCollection).GetProperty(
                            "Item",
                            typeof(PropertyDescriptor),
                            new[] { typeof(string) }
                        ),
                        Expression.Constant(
                            "Name"
                        )
                    )
                ),
                Expression.Assign(
                    indexVariable,
                    Expression.Constant(
                        0,
                        typeof(int)
                    )
                ),
                Expression.Assign(
                    resultVariable,
                    Expression.Constant(
                        true
                    )
                ),
                Expression.Loop(
                    Expression.IfThenElse(
                        Expression.LessThan(
                            indexVariable,
                            Expression.Property(
                                Expression.Convert(
                                    listParameter,
                                    typeof(ICollection)
                                ),
                                "Count"
                            )
                        ),
                        Expression.IfThenElse(
                            Expression.Equal(
                                Expression.Constant(
                                    null
                                ),
                                Expression.Call(
                                    propertyDescriptorVariable,
                                    "GetValue",
                                    Type.EmptyTypes,
                                    Expression.Property(
                                        Expression.Convert(
                                            listParameter,
                                            typeof(IList)
                                        ),
                                        "Item",
                                        indexVariable
                                    )
                                )
                            ),
                            Expression.Block(
                                Expression.Assign(
                                    resultVariable,
                                    Expression.Constant(
                                        false
                                    )
                                ),
                                Expression.Break(
                                    @break
                                )
                            ),
                            Expression.PostIncrementAssign(
                                indexVariable
                            )
                        ),
                        Expression.Break(
                            @break
                        )
                    ),
                    @break
                ),
                resultVariable
            ),
            listParameter
        );
        bool isEveryNameNotNull = lambdaExpression.Compile().Invoke(list);
3
2/24/2011 4:18:44 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