[C#] Serialize.Linq 簡單使用介紹

2017-01-05

最近有一些特別的需求。我需要在A 端將一個LINQ 的表述式(Expression) 將他序列化之後變成文字或是byte[] 傳遞到B端,進行執行,這邊做一下簡單介紹也避免自己忘記。
A端(Namespace : TestEXPA ) :
1.透過Nuget 取得Serialize.Linq
Image 533

2. 建立一個物件當作sample 這邊我叫 User

    public class User
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public DateTime Birth { get; set; }
        public int Age { get; set; }

    }

3. 開始來寫程式這裡面我是用一些簡單的LINQ 表述  ,針對一群User[] 進行查詢Name 含有99 並且排序使用Age

//predicate: 敘述語

var predicate = (Expression<Func<User[], IEnumerable<User>>>)
(
      x => x.Where(y => y.Name.Contains("99"))
            .OrderByDescending(z => z.Age)
);

4.將他之後將這predicate 進行序列化,我們將他存成test.txt

var serializer = new ExpressionSerializer(new Serialize.Linq.Serializers.JsonSerializer());
var expString = serializer.SerializeText(predicate);
System.IO.File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + "test.txt", expString);

5. 那test.txt 檔案內容大概長這樣

{"__type":"LambdaExpressionNode:#Serialize.Linq.Nodes","NodeType":18,"Type":{"GenericArguments":[{"Name":"TestEXPA.User[]"},{"GenericArguments":[{"Name":"TestEXPA.User"}],"Name":"System.Collections.Generic.IEnumerable`1"}],"Name":"System.Func`2"},"Body":{"__type":"MethodCallExpressionNode:#Serialize.Linq.Nodes","NodeType":6,"Type":{"GenericArguments":[{"Name":"TestEXPA.User"}],"Name":"System.Linq.IOrderedEnumerable`1"},"Arguments":[{"__type":"MethodCallExpressionNode:#Serialize.Linq.Nodes","NodeType":6,"Type":{"GenericArguments":[{"Name":"TestEXPA.User"}],"Name":"System.Collections.Generic.IEnumerable`1"},"Arguments":[{"__type":"ParameterExpressionNode:#Serialize.Linq.Nodes","NodeType":38,"Type":{"Name":"TestEXPA.User[]"},"Name":"x"},{"__type":"LambdaExpressionNode:#Serialize.Linq.Nodes","NodeType":18,"Type":{"GenericArguments":[{"Name":"TestEXPA.User"},{"Name":"System.Boolean"}],"Name":"System.Func`2"},"Body":{"__type":"MethodCallExpressionNode:#Serialize.Linq.Nodes","NodeType":6,"Type":{"Name":"System.Boolean"},"Arguments":[{"__type":"ConstantExpressionNode:#Serialize.Linq.Nodes","NodeType":9,"Type":{"Name":"System.String"},"Value":"99"}],"Method":{"DeclaringType":{"Name":"System.String"},"Signature":"Boolean Contains(System.String)"},"Object":{"__type":"MemberExpressionNode:#Serialize.Linq.Nodes","NodeType":23,"Type":{"Name":"System.String"},"Expression":{"__type":"ParameterExpressionNode:#Serialize.Linq.Nodes","NodeType":38,"Type":{"Name":"TestEXPA.User"},"Name":"y"},"Member":{"DeclaringType":{"Name":"TestEXPA.User"},"Signature":"System.String Name"}}},"Parameters":[{"__type":"ParameterExpressionNode:#Serialize.Linq.Nodes","NodeType":38,"Type":{"Name":"TestEXPA.User"},"Name":"y"}]}],"Method":{"DeclaringType":{"Name":"System.Linq.Enumerable"},"Signature":"System.Collections.Generic.IEnumerable`1[TSource] Where[TSource](System.Collections.Generic.IEnumerable`1[TSource], System.Func`2[TSource,System.Boolean])","GenericArguments":[{"Name":"TestEXPA.User"}],"IsGenericMethod":true}},{"__type":"LambdaExpressionNode:#Serialize.Linq.Nodes","NodeType":18,"Type":{"GenericArguments":[{"Name":"TestEXPA.User"},{"Name":"System.Int32"}],"Name":"System.Func`2"},"Body":{"__type":"MemberExpressionNode:#Serialize.Linq.Nodes","NodeType":23,"Type":{"Name":"System.Int32"},"Expression":{"__type":"ParameterExpressionNode:#Serialize.Linq.Nodes","NodeType":38,"Type":{"Name":"TestEXPA.User"},"Name":"z"},"Member":{"DeclaringType":{"Name":"TestEXPA.User"},"Signature":"Int32 Age"}},"Parameters":[{"__type":"ParameterExpressionNode:#Serialize.Linq.Nodes","NodeType":38,"Type":{"Name":"TestEXPA.User"},"Name":"z"}]}],"Method":{"DeclaringType":{"Name":"System.Linq.Enumerable"},"Signature":"System.Linq.IOrderedEnumerable`1[TSource] OrderByDescending[TSource,TKey](System.Collections.Generic.IEnumerable`1[TSource], System.Func`2[TSource,TKey])","GenericArguments":[{"Name":"TestEXPA.User"},{"Name":"System.Int32"}],"IsGenericMethod":true}},"Parameters":[{"__type":"ParameterExpressionNode:#Serialize.Linq.Nodes","NodeType":38,"Type":{"Name":"TestEXPA.User[]"},"Name":"x"}]}

B端還原執行端(Namespace : TestEXPB ):

6.開另一個新的專案命名為TestEXPB 專案一樣跟步驟1,2 一樣引入Serialize.Linq 並且建立一樣的User 物件

7. 建立假資料 :

var ALL_USER = new List<User>();

for (int i = 1; i <= 1000; i++)
{
   ALL_USER.Add(new User
   {
        Age = i,
        Id = "USER" + i,
        Name = "DONMA-" + i
    });

}


8.還原表述式,首先我們將步驟4產出的test.txt 複製到專案下面,接下來就是還原的Code

var serializer = new ExpressionSerializer(new Serialize.Linq.Serializers.JsonSerializer());

var expStr = File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + "test.txt");

var predicateDeserialized = serializer.DeserializeText(expStr);

9.執行後印出來

var expressionFunc = ((Expression<Func<User[], IEnumerable<User>>>)predicateDeserialized).Compile();
var result = expressionFunc(ALL_USER.ToArray());
foreach (var c in result)
{
       Response.Write(c.Name + "<br />");
}

image

10. 為何會錯呢,因為那是在TestEXPA 的namespace 下建立的User 跟這專案的不同,這時候我們做一個動作取巧一下,我們打開text.txt 將 TestEXPA.User 取代成 TestEXPB.User ,之後再執行

image

結果:
image

這樣就完成了,筆記一下。


當麻許的超技八 2014 | Donma Hsu Design.