Как связать IValueConverter в Linq для преобразования свойств - PullRequest
0 голосов
/ 29 февраля 2012

Как преобразовать значение свойства в значение, которое видит пользователь?

Пример:

PropertyValue = 0
TextBox.Text = "zero"
Converter convert from 0 --> "zero"

UserInput для фильтрации: value = "zero"

==> предложение where "value = \" zero \ "" "

, но в моем linq я получаю PropertyValue 0 по сравнению с userInput" zero "

Я извлек преобразователи связанных значений вмассив. Таким образом, у меня есть экземпляр преобразователя для преобразования свойства из моей модели с помощью converter.Convert (propValue, null, null, null)

1) Есть ли способ сделать это с помощью обычного синтаксиса linq. Iобнаружил, что если массив параметров будет иметь только словарь, он будет преобразован в расширение с именем dict в Dynamic.cs. Может ли это помочь? Мой фактический linq:

Создание запроса:

var queryableList = collection.AsQueryable();
return queryableList.Provider.CreateQuery(
    Expression.Call(
        typeof(Queryable), "Cast",
        new Type[] { itemType },
        queryableList.Expression));

Назначьте filterString:

ParameterExpression[] parameterExpressions = new ParameterExpression[] {Expression.Parameter(Source.ItemType)};
ExpressionParser parser = new ExpressionParser(Source.ColumnInfoDict, parameterExpressions, filterText, new object[0]);

LambdaExpression lambda  =Expression.Lambda(parser.Parse(typeof(bool)), parameterExpressions);

var source = Queryable;
mQuery = source.Provider.CreateQuery(
         Expression.Call(
              typeof(Queryable), "Where",
              new Type[] { Source.ItemType },
              source.Expression, Expression.Quote(lambda))).Cast<object>();

2) Конвертер также предоставляется System.Linq.Dynamic.ExpressonParser. Я надеялся найти способ реализовать Expression вокруг PropertyValue.Я не нахожу способ построить ExpressionCall, поэтому, когда фильтрация будет выполнена, значение из модели будет преобразовано в отображаемое значение перед выполнением сравнения.

Я пробовал это, где left - это мое PropertyExpression:

if(converter != null)
{
   Console.Out.WriteLine(left.NodeType);

   MethodInfo methodInfo = typeof (IValueConverter).GetMethod("Convert");
   Expression[] arguments = new Expression[] {left,null,null,null};
   left= Expression.Call(**converterExpression**, methodInfo,arguments);
}

Но как я могу построить converterExpression ?И будет ли это работать ??

1 Ответ

0 голосов
/ 01 марта 2012

Я нашел следующее решение.В System.Linq.Dynamic.ExpressonParser я добавляю метод:

private Expression ProvideValueConverter(Expression expr)
{
    Expression result = expr;
    if (mItemInfo != null)
    {
        IValueConverter converter = mItemInfo.Converter;
        if(converter != null)
        {

            Expression objTypedExpr =  Expression.Convert(expr, typeof(object));
            MethodInfo methodInfo = typeof(IValueConverter).GetMethod("Convert");

            Expression[] arguments = new Expression[] { objTypedExpr, 
                                                        Expression.Default(typeof(Type)),
                                                        Expression.Default(typeof(object)),
                                                        Expression.Default(typeof(CultureInfo))

            };
            ConstantExpression converterExpression = Expression.Constant(converter);
            MethodCallExpression callExpression = Expression.Call(converterExpression, methodInfo, arguments);
            result = Expression.Convert(callExpression, mItemInfo.ItemType);
        }
    }
    return result;
}

Я вызываю этот метод перед возвратом Property-oder FieldExpression:

Expression ParseMemberAccess(Type type, Expression instance) {
// some code.....
    else {
        MemberInfo member = FindPropertyOrField(type, id, instance == null);

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

mItemInfo - объект, заполненный вне DLINQс соответствующими данными.Затем он передается в качестве параметра в DLINQ.Параметр является надписью для fieldNames-IColumnInfoObjects.В методе ParseIdentifier вы можете извлечь IColumnInfoObject из формы dict.

...