简体   繁体   中英

How to bind an IValueConverter in Linq to convert the properties

How can I convert the property value to the value the user see?

Example:

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

UserInput for filtering: value="zero"

==> the where clause "value=\\"zero\\"""

but in my linq I get the PropertyValue 0 compared with userInput "zero"

I have extracted the binded value converters to an array. so I have the converter instance to convert the property from my model with converter.Convert(propValue, null, null, null)

1) Is there a way to do this with normal linq syntax. I found, that if the paramter array will have only a dictionary, it will be converted to an dict named extension in Dynamic.cs. Can this perhaps help? My actual linq is:

Creating Queryable:

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

Assign the 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) The converter is also provided to the System.Linq.Dynamic.ExpressonParser. I hoped to find a way to implement a Expression around the PropertyValue. But I don't find a way to construct a ExpressionCall, so when the filtering is done, the value from the model will be converted to the displayed value bevor doing the comparison.

I tried this where left is my 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);
}

But how can I construct the converterExpression ? And will this work??

I found the follwoing solution. In System.Linq.Dynamic.ExpressonParser I add the method:

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

I call This method before returning the 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 is a Object filled outside DLINQ with apropriate Data. It is than passed as an parameter to DLINQ. The parameter is a dict with fieldNames-IColumnInfoObjects. In the ParseIdentifier mehod you can extract the IColumnInfoObject form the dict.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM