Как сделать Linq на ITypedList? - PullRequest
       7

Как сделать Linq на ITypedList?

3 голосов
/ 05 августа 2010

Пока что я считаю, что Linq можно использовать для существующих полей и свойств класса, а не для виртуальных свойств. Другими словами, ITypedList не может работать с Linq даже динамическим Linq.

Я попробовал следующий код:

    IQueryable contact ; ...

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

Затем я встретил исключение «Нет связанного имени свойства или поле« Клиент »в типе« Контакт »».

Я проследил в динамический Linq и обнаружил, что следующий код вызвал исключение:

            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);

в методе Expression ParseMemberAccess (тип Type, экземпляр Expression).

Очевидно, что в Linq поддерживается только реальный член полей и свойств.

Но я все еще ожидаю, что кто-то, возможно, нашел способ использовать Linq для виртуальных свойств.

Если вы найдете способ сделать это, пожалуйста, поделитесь своим опытом.

Заранее спасибо,

Ин

1 Ответ

2 голосов
/ 24 февраля 2011

Этот код не намного лучше, чем код, который вы написали бы без выражений linq, но здесь он идет.

В этом коде предполагается, что ваш ITypedList также является IList. Получает дескриптор свойства для требуемого свойства и проверяет каждый элемент в коллекции, выполняя то, что составляет для (int i = 0; i <((ICollection) list) .Count; i ++) { ... } </p>

        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);
...