[C#] Serialize.Linq 簡單使用介紹
2017-01-05
最近有一些特別的需求。我需要在A 端將一個LINQ 的表述式(Expression) 將他序列化之後變成文字或是byte[] 傳遞到B端,進行執行,這邊做一下簡單介紹也避免自己忘記。
A端(Namespace : TestEXPA ) :
1.透過Nuget 取得Serialize.Linq
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 />"); }
10. 為何會錯呢,因為那是在TestEXPA 的namespace 下建立的User 跟這專案的不同,這時候我們做一個動作取巧一下,我們打開text.txt 將 TestEXPA.User 取代成 TestEXPB.User ,之後再執行
這樣就完成了,筆記一下。