用变量序列化表达式

本文关键字:表达式 序列化 变量 | 更新日期: 2023-09-27 18:17:26

我写了一些类来序列化System.Linq.Expressions到DataContracts,以便能够通过WCF发送。效果很好。问题是,当我想序列化一个有变量的表达式时。下面是解释这个问题的一个例子:

public class Foo
{
    public string Name { get; set; }
}
// CASE 1
Expression<Func<Foo, bool>> lambda = foo => foo.Name == "Test";
Console.WriteLine(lambda);
// OUTPUT: foo => (foo.Name == "Test")
// CASE 2
var variable = "Test";
lambda = foo => foo.Name == variable;            
this.AssertExpression(lambda, "Class Lambda expression with variable.");
// OUTPUT: foo => (foo.Name == value(MyTest+<>c__DisplayClass0).variable)

我序列化CASE 2表达式没有问题,但是我序列化的数据是无用的,因为在服务端,没有什么可以解析value(MyTest+<>c__DisplayClass0).variable

所以我需要在序列化该表达式之前解析变量,以便CASE 2表达式序列化为与CASE1

用变量序列化表达式

相同的结果

对不起,VB,但以下摘录是我在评论中所指的代码位。我不认为它涵盖了所有的基础(即。它可能没有深入到足够的程度,所以一定要测试它)但是对于简单的大多数例子,它是有效的:

代码基于以下MSDN表达式访问器示例:

class CustomExpressionWalker<TSource> : ExpressionVisitor
{
    protected override Expression VisitMemberAccess(MemberExpression m)
    {
        if (m.Member.DeclaringType != typeof(TSource))
        {
            // We are accessing a member/variable on a class
            // We need to descend the tree through the navigation properties and eventually derive a constant expression
            return this.VisitMemberAccess(m, m.Type);
        }
        throw new NotImplementedException();
    }
    protected Expression VisitMemberAccess(MemberExpression m, Type expectedType)
    {
        if (m.Expression.NodeType == ExpressionType.Constant)
        {
            // We are at the end of the member expression 
            // i.e. MyClass.Something.Something.Value <-- we're at the Value part now
            ConstantExpression constant = (ConstantExpression)m.Expression;
            return Expression.Constant(m.Expression.Type.GetFields().Single(n => n.FieldType == expectedType && m.Member.Name.Contains(n.Name)).GetValue(constant.Value));
        }
        else if (m.Member.DeclaringType == typeof(TSource))
        {
            // I'm unsure of your current implementation but the original Member access
            // regarding serializing the expression, but if the code reaches here a nested
            // MemberAccess has landed on a Property/variable of type TSource, so you'll need
            // to decide whether to serialize here or not.  For example, if TSource was of 
            // type "myClass", it could be 
            // (myOtherClass x) => x.myClass
            throw new NotImplementedException();
        }
        else if (m.Member.DeclaringType == typeof(Nullable))
        {
            // never got round to implementing this as we don't need it yet
            // if you want to deal with Nullable<T> you're going to have to 
            // examine the logic here
            throw new NotImplementedException();
        }
        else
        {
            // continue walking the member access until we derive the constant
            return this.VisitMemberAccess((MemberExpression)m.Expression, expectedType);
        }
    }
}   

希望这对你有帮助!

编辑:我原来的问题是,当MemberAccess是非TSource类时,我没有继续走树,上面的逻辑实际上应该递归地根除这些情况,所以忽略我原来的评论。我已经离开了Nullable<T>子句(在 else if )语句,因为我不认为现有的逻辑将涵盖这些情况,它也可能与泛型类斗争。

那就是说,这应该对你有好处。如果你没有使用表达式访问者,你能提供更多的细节/代码吗?

祝你好运!