文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>关于.Net Remoting中Lambda表达式的串行化问题

关于.Net Remoting中Lambda表达式的串行化问题

时间:2010-08-17  来源:reinstallsys

最近的一个项目中需要使用.Net Remoting来进行Client端与Server端的通信,其中Server端有一个数据库查询方法使用Lambda表达式作为参数,Client端将需要查询的条件以Lambda表达式的形式传给Server端运行然后返回查询结果,Server端函数如下:

 

        public List<object> SearchEntities<T>(Expression<Func<T, bool>> expression) where T : class, new()
        {
            DataClassesDataContext dc = new DataClassesDataContext(SQLiteHelper.GetConnection());
            Table<T> tables = dc.GetTable<T>();
            return tables.Where(expression).ToList();
        }

 

使用时发现Linq的Expression类没有标记Serializable,所以没法串行化传递该参数。于是想找到一个可串行化对象作为中间对象,将Lambda表达式转成这个中间对象传给Server端,Server端再将其还原成Lambda表达式,最后在Server端进行查询,如图:

 

 

 

在网上找到了三种方法可以将Expression转换成可串行化的对象,但是使用过程中发现这些方法都有问题:

 

1. 使用Dynamic Expression类,本来设想使用Expression.ToString()方法将Expression转换成字符串,然后将该字符串传递给Server端,Server端再使用ParseLambda方法将字符串转换成Expression,但是发现DynamicExpression类的ParseLambda方法中的string expression变量接收的是这个类自己定义的一套类似于Lambda语法的表达式,所以Expression.ToString()方法生成的字符串无法使用ParseLambda方法将其转换成Expression对象。

 

 

 

public void TestDynamicExpression()
{
    //not work!
    Expression<Func<UserInfo, bool>> expression = u => u.UserName == "admin";
    string expressionStr = expression.ToString();
    Expression<Func<UserInfo, bool>> result = DynamicExpression.ParseLambda<UserInfo, bool>(expressionStr);
}

 

2. 使用Expression Tree Serialization类,该类可以将Expression串行化成XElement对象,也可以将XElement对象反串行化成Expression。

Expression<Func<int, int, int>> addExpr = (x, y) => x + y;
ExpressionSerializer serializer = new ExpressionSerializer();
XElement addXml = serializer.Serialize(addExpr);
Expression<Func<int,int,int>> addExpResult = serializer.Deserialize<Func<int,int,int>>(addXml);

 

 

本以为这个类可以很完美的解决.Net Remoting中Expression无法串行化的问题,但是在使用过程中发现还有下面的问题:

 

    class Program
    {
        static void Main(string[] args)
        {
            //Test1: work!
            Expression<Func<UserInfo, bool>> expression = u => u.UserName == "admin";
            XElement xml = ExpressionSerializer.Serialize(expression);
            Expression<Func<UserInfo, bool>> result = ExpressionSerializer.Deserialize<Func<UserInfo, bool>>(xml);

            //Test2: not work!
            BLL bll = new BLL("admin");
            Expression<Func<UserInfo, bool>> expression1 = u => u.UserName == bll.value;
            XElement xml1 = ExpressionSerializer.Serialize(expression1);
            Expression<Func<UserInfo, bool>> r = ExpressionSerializer.Deserialize<Func<UserInfo, bool>>(xml1);
        }
    }

    public class BLL
    {
        public string value { get; set; }

        public BLL(string value)
        {
            this.value = value;
        }
    }

 

 

Test1是可以通过的,expression中的lambda表达式翻译成 u => (u.UserName = "admin"),因为"admin"是常量所以直接添加到表达式里。

Test2无法通过测试,expression1中的lambda表达式翻译成 u=> (u.UserName = TestServer.Program+<>c__DisplayClass0.value),因为value是BLL类的成员,所以就翻译成了一个类.成员的形式,但是这个方法在Deserialize的时候,就无法翻译TestServer.Program+<>c__DisplayClass0的类型,而且在Server端也无法知道BLL类的实例中value的值。

 

3. CodeDom, 这种方法的问题和上面的一样,也是当变量包含在一个类型中的时候,无法将真正的值变成Expression中的值。

 

public void Test()
{
    //not work!
    BLL bll = new BLL("admin");
    Expression<Func<UserInfo, bool>> expression = u => u.UserName == bll.value;
    string expressionStr = expression.ToString();

    Dictionary<string, string> providerOptions = new Dictionary<string, string>();
    providerOptions.Add("CompilerVersion", "v3.5");
    CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions);
    CompilerResults results = provider.CompileAssemblyFromSource
    (
        new CompilerParameters(new[] { "System.Core.dll" }),
        @"using System;
        using System.Linq.Expressions;

        class foo
        {
            public static Expression<Func<UserInfo, bool>> GetExpression()
            {
                return " + expressionStr + @";
            }
        }"
    );

    Expression<Func<UserInfo, bool>> result = (Expression<Func<UserInfo, bool>>)results.CompiledAssembly.GetType("foo").GetMethod("GetExpression").Invoke(null, null);
}

 

 

 上面三个方法花了一整天的时间试验以后发现都不好使,所以冒昧的发到首页想向大家请教一下,关于Lambda表达式的串行化问题大家是如何解决的?多谢^_^

 

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载