Giter Site home page Giter Site logo

serialize.linq's Introduction

Serialize.Linq

Serialize.Linq is a .NET library that provides functionality to serialize and deserialize LINQ expressions. This library is useful in scenarios where you need to send LINQ expressions over the wire or persist them in a database.

Features

  • Serialize and deserialize LINQ expressions to XML, JSON, and binary formats.
  • Supports various types of expressions, including binary, unary, member access, lambda, and more.
  • Extensible design that allows you to add support for custom expressions.

Getting Started

Installation

You can install Serialize.Linq via NuGet:

Install-Package Serialize.Linq

Usage

Here's a simple example of how to use Serialize.Linq:

// Create an expression
Expression<Func<int, bool>> expression = num => num < 5;

// Create a serializer
var serializer = new ExpressionSerializer(new JsonSerializer());

// Serialize the expression
string serializedExpression = serializer.SerializeText(expression);

// Deserialize the expression
var deserializedExpression = serializer.DeserializeText(serializedExpression);

Contributing

We welcome contributions to Serialize.Linq! If you'd like to contribute, please fork the repository, make your changes, and submit a pull request. If you're not sure where to start, take a look at our open issues.

For bugs: make sure you create a unit test, so it is easier for me to reproduce and fix it.

You can always buy me a coffee ☕.

Testing

Serialize.Linq has a comprehensive test suite. You can run the tests using your preferred test runner.

Supported Platforms (or known to work with)

  • .NET 7.0
  • .NET 6.0
  • .NET 5.0
  • .NET 4.8

License

Serialize.Linq is licensed under the MIT License. See the LICENSE file for more details.

serialize.linq's People

Contributors

artemnf avatar dependabot[bot] avatar esskar avatar jogibear9988 avatar olabacker avatar olegnadymov avatar stefh avatar vcaraulean avatar vsoldatkin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

serialize.linq's Issues

Nuget package issue

When I used nuget package, I could serialize below expression but deserialize is failing:

ExpressionSerializer es = new ExpressionSerializer(new JsonSerializer());
Expression<Func<IEnumerable, double>> avg = (ps) => ps.Average(p => p.Price);
string serializedText = es.SerializeText(count);
Expression<Func<IEnumerable, double>> expressionDeserialized = (Expression<Func<IEnumerable, double>>)es.DeserializeText(serializedText);

This issue is not happening when I get source and build the dll and reference it in application. Any idea what's wrong with Nuget version?.

ToExpressionNode method causes "stack overflow" exception.

I have a expression,it contains 800 boolean expessions, when I invoke ToExpressionNode method,the visual studio gives a "stack overflow " exception. pls help me,thanks.

ExpressionBool.ToString()
"x => ((x.Account == "799") OrElse ((x.Account == "798") OrElse ((x.Account == "797") OrElse ((x.Account == "796") OrElse ((x.Account == "795") OrElse ((x.Account == "794") OrElse ((x.Account == "793") OrElse ((x.Account == "792") OrElse ((x.Account == "791") OrElse ((x.Account == "790") OrElse ((x.Account == "789") OrElse ((x.Account == "788") OrElse ((x.Account == "787") OrElse ((x.Account == "786") OrElse ((x.Account == "785") OrElse ((x.Account == "784") OrElse ((x.Account == "783") OrElse ((x.Account == "782") OrElse ((x.Account == "781") OrElse ((x.Account == "780") OrElse ((x.Account == "779") OrElse ((x.Account == "778") OrElse ((x.Account == "777") OrElse ((x.Account == "776") OrElse ((x.Account == "775") OrElse ((x.Account == "774") OrElse ((x.Account == "773") OrElse ((x.Account == "772") OrElse ((x.Account == "771") OrElse ((x.Account == "770") OrElse ((x.Account == "769") OrElse ((x.Account == "768") OrElse ((x.Account == "767") OrE
lse ((x.Account == "766") OrElse ((x.Account == "765") OrElse ((x.Account == "764") OrElse ((x.Account == "763") OrElse ((x.Account == "762") OrElse ((x.Account == "761") OrElse ((x.Account == "760") OrElse ((x.Account == "759") OrElse ((x.Account == "758") OrElse ((x.Account == "757") OrElse ((x.Account == "756") OrElse ((x.Account == "755") OrElse ((x.Account == "754") OrElse ((x.Account == "753") OrElse ((x.Account == "752") OrElse ((x.Account == "751") OrElse ((x.Account == "750") OrElse ((x.Account == "749") OrElse ((x.Account == "748") OrElse ((x.Account == "747") OrElse ((x.Account == "746") OrElse ((x.Account == "745") OrElse ((x.Account == "744") OrElse ((x.Account == "743") OrElse ((x.Account == "742") OrElse ((x.Account == "741") OrElse ((x.Account == "740") OrElse ((x.Account == "739") OrElse ((x.Account == "738") OrElse ((x.Account == "737") OrElse ((x.Account == "736") OrElse ((x.Account == "735") OrElse ((x.Account == "734") OrEls
e ((x.Account == "733") OrElse ((x.Account == "732") OrElse ((x.Account == "731") OrElse ((x.Account == "730") OrElse ((x.Account == "729") OrElse ((x.Account == "728") OrElse ((x.Account == "727") OrElse ((x.Account == "726") OrElse ((x.Account == "725") OrElse ((x.Account == "724") OrElse ((x.Account == "723") OrElse ((x.Account == "722") OrElse ((x.Account == "721") OrElse ((x.Account == "720") OrElse ((x.Account == "719") OrElse ((x.Account == "718") OrElse ((x.Account == "717") OrElse ((x.Account == "716") OrElse ((x.Account == "715") OrElse ((x.Account == "714") OrElse ((x.Account == "713") OrElse ((x.Account == "712") OrElse ((x.Account == "711") OrElse ((x.Account == "710") OrElse ((x.Account == "709") OrElse ((x.Account == "708") OrElse ((x.Account == "707") OrElse ((x.Account == "706") OrElse ((x.Account == "705") OrElse ((x.Account == "704") OrElse ((x.Account == "703") OrElse ((x.Account == "702") OrElse ((x.Account == "701") OrElse
((x.Account == "700") OrElse ((x.Account == "699") OrElse ((x.Account == "698") OrElse ((x.Account == "697") OrElse ((x.Account == "696") OrElse ((x.Account == "695") OrElse ((x.Account == "694") OrElse ((x.Account == "693") OrElse ((x.Account == "692") OrElse ((x.Account == "691") OrElse ((x.Account == "690") OrElse ((x.Account == "689") OrElse ((x.Account == "688") OrElse ((x.Account == "687") OrElse ((x.Account == "686") OrElse ((x.Account == "685") OrElse ((x.Account == "684") OrElse ((x.Account == "683") OrElse ((x.Account == "682") OrElse ((x.Account == "681") OrElse ((x.Account == "680") OrElse ((x.Account == "679") OrElse ((x.Account == "678") OrElse ((x.Account == "677") OrElse ((x.Account == "676") OrElse ((x.Account == "675") OrElse ((x.Account == "674") OrElse ((x.Account == "673") OrElse ((x.Account == "672") OrElse ((x.Account == "671") OrElse ((x.Account == "670") OrElse ((x.Account == "669") OrElse ((x.Account == "668") OrElse ((
x.Account == "667") OrElse ((x.Account == "666") OrElse ((x.Account == "665") OrElse ((x.Account == "664") OrElse ((x.Account == "663") OrElse ((x.Account == "662") OrElse ((x.Account == "661") OrElse ((x.Account == "660") OrElse ((x.Account == "659") OrElse ((x.Account == "658") OrElse ((x.Account == "657") OrElse ((x.Account == "656") OrElse ((x.Account == "655") OrElse ((x.Account == "654") OrElse ((x.Account == "653") OrElse ((x.Account == "652") OrElse ((x.Account == "651") OrElse ((x.Account == "650") OrElse ((x.Account == "649") OrElse ((x.Account == "648") OrElse ((x.Account == "647") OrElse ((x.Account == "646") OrElse ((x.Account == "645") OrElse ((x.Account == "644") OrElse ((x.Account == "643") OrElse ((x.Account == "642") OrElse ((x.Account == "641") OrElse ((x.Account == "640") OrElse ((x.Account == "639") OrElse ((x.Account == "638") OrElse ((x.Account == "637") OrElse ((x.Account == "636") OrElse ((x.Account == "635") OrElse ((x.
Account == "634") OrElse ((x.Account == "633") OrElse ((x.Account == "632") OrElse ((x.Account == "631") OrElse ((x.Account == "630") OrElse ((x.Account == "629") OrElse ((x.Account == "628") OrElse ((x.Account == "627") OrElse ((x.Account == "626") OrElse ((x.Account == "625") OrElse ((x.Account == "624") OrElse ((x.Account == "623") OrElse ((x.Account == "622") OrElse ((x.Account == "621") OrElse ((x.Account == "620") OrElse ((x.Account == "619") OrElse ((x.Account == "618") OrElse ((x.Account == "617") OrElse ((x.Account == "616") OrElse ((x.Account == "615") OrElse ((x.Account == "614") OrElse ((x.Account == "613") OrElse ((x.Account == "612") OrElse ((x.Account == "611") OrElse ((x.Account == "610") OrElse ((x.Account == "609") OrElse ((x.Account == "608") OrElse ((x.Account == "607") OrElse ((x.Account == "606") OrElse ((x.Account == "605") OrElse ((x.Account == "604") OrElse ((x.Account == "603") OrElse ((x.Account == "602") OrElse ((x.Ac
count == "601") OrElse ((x.Account == "600") OrElse ((x.Account == "599") OrElse ((x.Account == "598") OrElse ((x.Account == "597") OrElse ((x.Account == "596") OrElse ((x.Account == "595") OrElse ((x.Account == "594") OrElse ((x.Account == "593") OrElse ((x.Account == "592") OrElse ((x.Account == "591") OrElse ((x.Account == "590") OrElse ((x.Account == "589") OrElse ((x.Account == "588") OrElse ((x.Account == "587") OrElse ((x.Account == "586") OrElse ((x.Account == "585") OrElse ((x.Account == "584") OrElse ((x.Account == "583") OrElse ((x.Account == "582") OrElse ((x.Account == "581") OrElse ((x.Account == "580") OrElse ((x.Account == "579") OrElse ((x.Account == "578") OrElse ((x.Account == "577") OrElse ((x.Account == "576") OrElse ((x.Account == "575") OrElse ((x.Account == "574") OrElse ((x.Account == "573") OrElse ((x.Account == "572") OrElse ((x.Account == "571") OrElse ((x.Account == "570") OrElse ((x.Account == "569") OrElse ((x.Acco
unt == "568") OrElse ((x.Account == "567") OrElse ((x.Account == "566") OrElse ((x.Account == "565") OrElse ((x.Account == "564") OrElse ((x.Account == "563") OrElse ((x.Account == "562") OrElse ((x.Account == "561") OrElse ((x.Account == "560") OrElse ((x.Account == "559") OrElse ((x.Account == "558") OrElse ((x.Account == "557") OrElse ((x.Account == "556") OrElse ((x.Account == "555") OrElse ((x.Account == "554") OrElse ((x.Account == "553") OrElse ((x.Account == "552") OrElse ((x.Account == "551") OrElse ((x.Account == "550") OrElse ((x.Account == "549") OrElse ((x.Account == "548") OrElse ((x.Account == "547") OrElse ((x.Account == "546") OrElse ((x.Account == "545") OrElse ((x.Account == "544") OrElse ((x.Account == "543") OrElse ((x.Account == "542") OrElse ((x.Account == "541") OrElse ((x.Account == "540") OrElse ((x.Account == "539") OrElse ((x.Account == "538") OrElse ((x.Account == "537") OrElse ((x.Account == "536") OrElse ((x.Accoun
t == "535") OrElse ((x.Account == "534") OrElse ((x.Account == "533") OrElse ((x.Account == "532") OrElse ((x.Account == "531") OrElse ((x.Account == "530") OrElse ((x.Account == "529") OrElse ((x.Account == "528") OrElse ((x.Account == "527") OrElse ((x.Account == "526") OrElse ((x.Account == "525") OrElse ((x.Account == "524") OrElse ((x.Account == "523") OrElse ((x.Account == "522") OrElse ((x.Account == "521") OrElse ((x.Account == "520") OrElse ((x.Account == "519") OrElse ((x.Account == "518") OrElse ((x.Account == "517") OrElse ((x.Account == "516") OrElse ((x.Account == "515") OrElse ((x.Account == "514") OrElse ((x.Account == "513") OrElse ((x.Account == "512") OrElse ((x.Account == "511") OrElse ((x.Account == "510") OrElse ((x.Account == "509") OrElse ((x.Account == "508") OrElse ((x.Account == "507") OrElse ((x.Account == "506") OrElse ((x.Account == "505") OrElse ((x.Account == "504") OrElse ((x.Account == "503") OrElse ((x.Account
== "502") OrElse ((x.Account == "501") OrElse ((x.Account == "500") OrElse ((x.Account == "499") OrElse ((x.Account == "498") OrElse ((x.Account == "497") OrElse ((x.Account == "496") OrElse ((x.Account == "495") OrElse ((x.Account == "494") OrElse ((x.Account == "493") OrElse ((x.Account == "492") OrElse ((x.Account == "491") OrElse ((x.Account == "490") OrElse ((x.Account == "489") OrElse ((x.Account == "488") OrElse ((x.Account == "487") OrElse ((x.Account == "486") OrElse ((x.Account == "485") OrElse ((x.Account == "484") OrElse ((x.Account == "483") OrElse ((x.Account == "482") OrElse ((x.Account == "481") OrElse ((x.Account == "480") OrElse ((x.Account == "479") OrElse ((x.Account == "478") OrElse ((x.Account == "477") OrElse ((x.Account == "476") OrElse ((x.Account == "475") OrElse ((x.Account == "474") OrElse ((x.Account == "473") OrElse ((x.Account == "472") OrElse ((x.Account == "471") OrElse ((x.Account == "470") OrElse ((x.Account ==
"469") OrElse ((x.Account == "468") OrElse ((x.Account == "467") OrElse ((x.Account == "466") OrElse ((x.Account == "465") OrElse ((x.Account == "464") OrElse ((x.Account == "463") OrElse ((x.Account == "462") OrElse ((x.Account == "461") OrElse ((x.Account == "460") OrElse ((x.Account == "459") OrElse ((x.Account == "458") OrElse ((x.Account == "457") OrElse ((x.Account == "456") OrElse ((x.Account == "455") OrElse ((x.Account == "454") OrElse ((x.Account == "453") OrElse ((x.Account == "452") OrElse ((x.Account == "451") OrElse ((x.Account == "450") OrElse ((x.Account == "449") OrElse ((x.Account == "448") OrElse ((x.Account == "447") OrElse ((x.Account == "446") OrElse ((x.Account == "445") OrElse ((x.Account == "444") OrElse ((x.Account == "443") OrElse ((x.Account == "442") OrElse ((x.Account == "441") OrElse ((x.Account == "440") OrElse ((x.Account == "439") OrElse ((x.Account == "438") OrElse ((x.Account == "437") OrElse ((x.Account ==
"436") OrElse ((x.Account == "435") OrElse ((x.Account == "434") OrElse ((x.Account == "433") OrElse ((x.Account == "432") OrElse ((x.Account == "431") OrElse ((x.Account == "430") OrElse ((x.Account == "429") OrElse ((x.Account == "428") OrElse ((x.Account == "427") OrElse ((x.Account == "426") OrElse ((x.Account == "425") OrElse ((x.Account == "424") OrElse ((x.Account == "423") OrElse ((x.Account == "422") OrElse ((x.Account == "421") OrElse ((x.Account == "420") OrElse ((x.Account == "419") OrElse ((x.Account == "418") OrElse ((x.Account == "417") OrElse ((x.Account == "416") OrElse ((x.Account == "415") OrElse ((x.Account == "414") OrElse ((x.Account == "413") OrElse ((x.Account == "412") OrElse ((x.Account == "411") OrElse ((x.Account == "410") OrElse ((x.Account == "409") OrElse ((x.Account == "408") OrElse ((x.Account == "407") OrElse ((x.Account == "406") OrElse ((x.Account == "405") OrElse ((x.Account == "404") OrElse ((x.Account == "4
03") OrElse ((x.Account == "402") OrElse ((x.Account == "401") OrElse ((x.Account == "400") OrElse ((x.Account == "399") OrElse ((x.Account == "398") OrElse ((x.Account == "397") OrElse ((x.Account == "396") OrElse ((x.Account == "395") OrElse ((x.Account == "394") OrElse ((x.Account == "393") OrElse ((x.Account == "392") OrElse ((x.Account == "391") OrElse ((x.Account == "390") OrElse ((x.Account == "389") OrElse ((x.Account == "388") OrElse ((x.Account == "387") OrElse ((x.Account == "386") OrElse ((x.Account == "385") OrElse ((x.Account == "384") OrElse ((x.Account == "383") OrElse ((x.Account == "382") OrElse ((x.Account == "381") OrElse ((x.Account == "380") OrElse ((x.Account == "379") OrElse ((x.Account == "378") OrElse ((x.Account == "377") OrElse ((x.Account == "376") OrElse ((x.Account == "375") OrElse ((x.Account == "374") OrElse ((x.Account == "373") OrElse ((x.Account == "372") OrElse ((x.Account == "371") OrElse ((x.Account == "370
") OrElse ((x.Account == "369") OrElse ((x.Account == "368") OrElse ((x.Account == "367") OrElse ((x.Account == "366") OrElse ((x.Account == "365") OrElse ((x.Account == "364") OrElse ((x.Account == "363") OrElse ((x.Account == "362") OrElse ((x.Account == "361") OrElse ((x.Account == "360") OrElse ((x.Account == "359") OrElse ((x.Account == "358") OrElse ((x.Account == "357") OrElse ((x.Account == "356") OrElse ((x.Account == "355") OrElse ((x.Account == "354") OrElse ((x.Account == "353") OrElse ((x.Account == "352") OrElse ((x.Account == "351") OrElse ((x.Account == "350") OrElse ((x.Account == "349") OrElse ((x.Account == "348") OrElse ((x.Account == "347") OrElse ((x.Account == "346") OrElse ((x.Account == "345") OrElse ((x.Account == "344") OrElse ((x.Account == "343") OrElse ((x.Account == "342") OrElse ((x.Account == "341") OrElse ((x.Account == "340") OrElse ((x.Account == "339") OrElse ((x.Account == "338") OrElse ((x.Account == "337"
) OrElse ((x.Account == "336") OrElse ((x.Account == "335") OrElse ((x.Account == "334") OrElse ((x.Account == "333") OrElse ((x.Account == "332") OrElse ((x.Account == "331") OrElse ((x.Account == "330") OrElse ((x.Account == "329") OrElse ((x.Account == "328") OrElse ((x.Account == "327") OrElse ((x.Account == "326") OrElse ((x.Account == "325") OrElse ((x.Account == "324") OrElse ((x.Account == "323") OrElse ((x.Account == "322") OrElse ((x.Account == "321") OrElse ((x.Account == "320") OrElse ((x.Account == "319") OrElse ((x.Account == "318") OrElse ((x.Account == "317") OrElse ((x.Account == "316") OrElse ((x.Account == "315") OrElse ((x.Account == "314") OrElse ((x.Account == "313") OrElse ((x.Account == "312") OrElse ((x.Account == "311") OrElse ((x.Account == "310") OrElse ((x.Account == "309") OrElse ((x.Account == "308") OrElse ((x.Account == "307") OrElse ((x.Account == "306") OrElse ((x.Account == "305") OrElse ((x.Account == "304")
OrElse ((x.Account == "303") OrElse ((x.Account == "302") OrElse ((x.Account == "301") OrElse ((x.Account == "300") OrElse ((x.Account == "299") OrElse ((x.Account == "298") OrElse ((x.Account == "297") OrElse ((x.Account == "296") OrElse ((x.Account == "295") OrElse ((x.Account == "294") OrElse ((x.Account == "293") OrElse ((x.Account == "292") OrElse ((x.Account == "291") OrElse ((x.Account == "290") OrElse ((x.Account == "289") OrElse ((x.Account == "288") OrElse ((x.Account == "287") OrElse ((x.Account == "286") OrElse ((x.Account == "285") OrElse ((x.Account == "284") OrElse ((x.Account == "283") OrElse ((x.Account == "282") OrElse ((x.Account == "281") OrElse ((x.Account == "280") OrElse ((x.Account == "279") OrElse ((x.Account == "278") OrElse ((x.Account == "277") OrElse ((x.Account == "276") OrElse ((x.Account == "275") OrElse ((x.Account == "274") OrElse ((x.Account == "273") OrElse ((x.Account == "272") OrElse ((x.Account == "271") Or
Else ((x.Account == "270") OrElse ((x.Account == "269") OrElse ((x.Account == "268") OrElse ((x.Account == "267") OrElse ((x.Account == "266") OrElse ((x.Account == "265") OrElse ((x.Account == "264") OrElse ((x.Account == "263") OrElse ((x.Account == "262") OrElse ((x.Account == "261") OrElse ((x.Account == "260") OrElse ((x.Account == "259") OrElse ((x.Account == "258") OrElse ((x.Account == "257") OrElse ((x.Account == "256") OrElse ((x.Account == "255") OrElse ((x.Account == "254") OrElse ((x.Account == "253") OrElse ((x.Account == "252") OrElse ((x.Account == "251") OrElse ((x.Account == "250") OrElse ((x.Account == "249") OrElse ((x.Account == "248") OrElse ((x.Account == "247") OrElse ((x.Account == "246") OrElse ((x.Account == "245") OrElse ((x.Account == "244") OrElse ((x.Account == "243") OrElse ((x.Account == "242") OrElse ((x.Account == "241") OrElse ((x.Account == "240") OrElse ((x.Account == "239") OrElse ((x.Account == "238") OrEl
se ((x.Account == "237") OrElse ((x.Account == "236") OrElse ((x.Account == "235") OrElse ((x.Account == "234") OrElse ((x.Account == "233") OrElse ((x.Account == "232") OrElse ((x.Account == "231") OrElse ((x.Account == "230") OrElse ((x.Account == "229") OrElse ((x.Account == "228") OrElse ((x.Account == "227") OrElse ((x.Account == "226") OrElse ((x.Account == "225") OrElse ((x.Account == "224") OrElse ((x.Account == "223") OrElse ((x.Account == "222") OrElse ((x.Account == "221") OrElse ((x.Account == "220") OrElse ((x.Account == "219") OrElse ((x.Account == "218") OrElse ((x.Account == "217") OrElse ((x.Account == "216") OrElse ((x.Account == "215") OrElse ((x.Account == "214") OrElse ((x.Account == "213") OrElse ((x.Account == "212") OrElse ((x.Account == "211") OrElse ((x.Account == "210") OrElse ((x.Account == "209") OrElse ((x.Account == "208") OrElse ((x.Account == "207") OrElse ((x.Account == "206") OrElse ((x.Account == "205") OrElse
((x.Account == "204") OrElse ((x.Account == "203") OrElse ((x.Account == "202") OrElse ((x.Account == "201") OrElse ((x.Account == "200") OrElse ((x.Account == "199") OrElse ((x.Account == "198") OrElse ((x.Account == "197") OrElse ((x.Account == "196") OrElse ((x.Account == "195") OrElse ((x.Account == "194") OrElse ((x.Account == "193") OrElse ((x.Account == "192") OrElse ((x.Account == "191") OrElse ((x.Account == "190") OrElse ((x.Account == "189") OrElse ((x.Account == "188") OrElse ((x.Account == "187") OrElse ((x.Account == "186") OrElse ((x.Account == "185") OrElse ((x.Account == "184") OrElse ((x.Account == "183") OrElse ((x.Account == "182") OrElse ((x.Account == "181") OrElse ((x.Account == "180") OrElse ((x.Account == "179") OrElse ((x.Account == "178") OrElse ((x.Account == "177") OrElse ((x.Account == "176") OrElse ((x.Account == "175") OrElse ((x.Account == "174") OrElse ((x.Account == "173") OrElse ((x.Account == "172") OrElse (
(x.Account == "171") OrElse ((x.Account == "170") OrElse ((x.Account == "169") OrElse ((x.Account == "168") OrElse ((x.Account == "167") OrElse ((x.Account == "166") OrElse ((x.Account == "165") OrElse ((x.Account == "164") OrElse ((x.Account == "163") OrElse ((x.Account == "162") OrElse ((x.Account == "161") OrElse ((x.Account == "160") OrElse ((x.Account == "159") OrElse ((x.Account == "158") OrElse ((x.Account == "157") OrElse ((x.Account == "156") OrElse ((x.Account == "155") OrElse ((x.Account == "154") OrElse ((x.Account == "153") OrElse ((x.Account == "152") OrElse ((x.Account == "151") OrElse ((x.Account == "150") OrElse ((x.Account == "149") OrElse ((x.Account == "148") OrElse ((x.Account == "147") OrElse ((x.Account == "146") OrElse ((x.Account == "145") OrElse ((x.Account == "144") OrElse ((x.Account == "143") OrElse ((x.Account == "142") OrElse ((x.Account == "141") OrElse ((x.Account == "140") OrElse ((x.Account == "139") OrElse ((x
.Account == "138") OrElse ((x.Account == "137") OrElse ((x.Account == "136") OrElse ((x.Account == "135") OrElse ((x.Account == "134") OrElse ((x.Account == "133") OrElse ((x.Account == "132") OrElse ((x.Account == "131") OrElse ((x.Account == "130") OrElse ((x.Account == "129") OrElse ((x.Account == "128") OrElse ((x.Account == "127") OrElse ((x.Account == "126") OrElse ((x.Account == "125") OrElse ((x.Account == "124") OrElse ((x.Account == "123") OrElse ((x.Account == "122") OrElse ((x.Account == "121") OrElse ((x.Account == "120") OrElse ((x.Account == "119") OrElse ((x.Account == "118") OrElse ((x.Account == "117") OrElse ((x.Account == "116") OrElse ((x.Account == "115") OrElse ((x.Account == "114") OrElse ((x.Account == "113") OrElse ((x.Account == "112") OrElse ((x.Account == "111") OrElse ((x.Account == "110") OrElse ((x.Account == "109") OrElse ((x.Account == "108") OrElse ((x.Account == "107") OrElse ((x.Account == "106") OrElse ((x.A
ccount == "105") OrElse ((x.Account == "104") OrElse ((x.Account == "103") OrElse ((x.Account == "102") OrElse ((x.Account == "101") OrElse ((x.Account == "100") OrElse ((x.Account == "99") OrElse ((x.Account == "98") OrElse ((x.Account == "97") OrElse ((x.Account == "96") OrElse ((x.Account == "95") OrElse ((x.Account == "94") OrElse ((x.Account == "93") OrElse ((x.Account == "92") OrElse ((x.Account == "91") OrElse ((x.Account == "90") OrElse ((x.Account == "89") OrElse ((x.Account == "88") OrElse ((x.Account == "87") OrElse ((x.Account == "86") OrElse ((x.Account == "85") OrElse ((x.Account == "84") OrElse ((x.Account == "83") OrElse ((x.Account == "82") OrElse ((x.Account == "81") OrElse ((x.Account == "80") OrElse ((x.Account == "79") OrElse ((x.Account == "78") OrElse ((x.Account == "77") OrElse ((x.Account == "76") OrElse ((x.Account == "75") OrElse ((x.Account == "74") OrElse ((x.Account == "73") OrElse ((x.Account == "72") OrElse ((x.
Account == "71") OrElse ((x.Account == "70") OrElse ((x.Account == "69") OrElse ((x.Account == "68") OrElse ((x.Account == "67") OrElse ((x.Account == "66") OrElse ((x.Account == "65") OrElse ((x.Account == "64") OrElse ((x.Account == "63") OrElse ((x.Account == "62") OrElse ((x.Account == "61") OrElse ((x.Account == "60") OrElse ((x.Account == "59") OrElse ((x.Account == "58") OrElse ((x.Account == "57") OrElse ((x.Account == "56") OrElse ((x.Account == "55") OrElse ((x.Account == "54") OrElse ((x.Account == "53") OrElse ((x.Account == "52") OrElse ((x.Account == "51") OrElse ((x.Account == "50") OrElse ((x.Account == "49") OrElse ((x.Account == "48") OrElse ((x.Account == "47") OrElse ((x.Account == "46") OrElse ((x.Account == "45") OrElse ((x.Account == "44") OrElse ((x.Account == "43") OrElse ((x.Account == "42") OrElse ((x.Account == "41") OrElse ((x.Account == "40") OrElse ((x.Account == "39") OrElse ((x.Account == "38") OrElse ((x.Accou
nt == "37") OrElse ((x.Account == "36") OrElse ((x.Account == "35") OrElse ((x.Account == "34") OrElse ((x.Account == "33") OrElse ((x.Account == "32") OrElse ((x.Account == "31") OrElse ((x.Account == "30") OrElse ((x.Account == "29") OrElse ((x.Account == "28") OrElse ((x.Account == "27") OrElse ((x.Account == "26") OrElse ((x.Account == "25") OrElse ((x.Account == "24") OrElse ((x.Account == "23") OrElse ((x.Account == "22") OrElse ((x.Account == "21") OrElse ((x.Account == "20") OrElse ((x.Account == "19") OrElse ((x.Account == "18") OrElse ((x.Account == "17") OrElse ((x.Account == "16") OrElse ((x.Account == "15") OrElse ((x.Account == "14") OrElse ((x.Account == "13") OrElse ((x.Account == "12") OrElse ((x.Account == "11") OrElse ((x.Account == "10") OrElse ((x.Account == "9") OrElse ((x.Account == "8") OrElse ((x.Account == "7") OrElse ((x.Account == "6") OrElse ((x.Account == "5") OrElse ((x.Account == "4") OrElse ((x.Account == "3"
) OrElse ((x.Account == "2") OrElse ((x.Account == "1") OrElse ((x.Account == "0") OrElse False))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))"

"let" in an expression is throwing an exception during serialization

I was getting an exception on code similar to:

from x in myArray
let testValue = myInput
where x == testValue 
select x

The exception is:

An exception of type 'System.InvalidOperationException' occurred in System.Core.dll but was not handled in user code

Additional information: variable '<>h__TransparentIdentifier2' of type '<>f__AnonymousType0`2[System.String,System.String]' referenced from scope '', but it is not defined

The issue is related to the code:

case MemberTypes.Property:
    constantValue = Expression.Lambda(memberExpression).Compile().DynamicInvoke();
    return true;

and I believe the problem arises from the fact that it's trying to get a value from a Parameter but the parameter has no value until it's executed

I updated the code to:

case MemberTypes.Property:
    if (memberExpression.Expression.NodeType == ExpressionType.Parameter) return false;
    constantValue = Expression.Lambda(memberExpression).Compile().DynamicInvoke();
    return true;

and this appears to have fixed the issue in all the scenarios I have run

SerializationContext lacking

Not sure if this would count as an issue or maybe it's more of a feature request or the likes (I'm no github guru so I might be doing something wrong here).

But basically what we're doing (as you might have guesed from my previous 'issue') is serializing an expression and then we're sending this string through NServiceBus and deserializing it. What I'm lacking at the moment is a ExpressionContext to be able to translate from a Dto Expression to an expression on our actual class.

If I dive into your code though I see;

public Expression DeserializeText(string text)
{
var node = this.TextSerializer.Deserialize(text);
return node == null ? null : node.ToExpression();
}

Surely adding an overload which does;

public Expression DeserializeText(string text, ExpressionContext expressionContext)
{
var node = this.TextSerializer.Deserialize(text);
return node == null ? null : node.ToExpression(expressionContext);
}

Should allow for me to simply state the expressioncontext right on the deserialization and would keep me from needing to cast the expression back to a ExpressionNode and then adding the context to turn it back into an expression.

Maybe i'm missing some super easy way of doing this though, it's entirely possible.

Assembly Version .NET45

Hi

In the NuGet Package, the assembly version for the .NET4.5 package is 1.2.2.0 instead of 1.2.3.0...
Could you correct that?

Thanks
Michel

NullReferenceException when deserializing expression with constant Guid

I'll look into it, but may be you'll spot the problem faster...

A test:

        [TestMethod]
        public void Deserialize_expression_with_guid_constant()
        {
            Expression<Func<Model, bool>> exp = model => model.Id != Guid.Empty;

            var serializer = new ExpressionSerializer(new JsonSerializer());
            var json = serializer.SerializeText(exp);

            var deserializedExp = serializer.DeserializeText(json);
            Assert.IsNotNull(deserializedExp);
        }

        class Model
        {
            public Guid Id { get; set; }
        }

Stack trace:

    at Serialize.Linq.Nodes.ConstantExpressionNode.set_Value(Object value) in ConstantExpressionNode.cs: line 86
   at ReadCFromJson(XmlReaderDelegator, XmlObjectSerializerReadContextComplexJson, XmlDictionaryString, XmlDictionaryString[])
   at System.Runtime.Serialization.Json.JsonClassDataContract.ReadJsonValueCore(XmlReaderDelegator jsonReader, XmlObjectSerializerReadContextComplexJson context)
   at System.Runtime.Serialization.Json.JsonDataContract.ReadJsonValue(XmlReaderDelegator jsonReader, XmlObjectSerializerReadContextComplexJson context)
   at System.Runtime.Serialization.Json.XmlObjectSerializerReadContextComplexJson.ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, ref DataContract dataContract)
   at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
   at ReadBFromJson(XmlReaderDelegator, XmlObjectSerializerReadContextComplexJson, XmlDictionaryString, XmlDictionaryString[])
   at System.Runtime.Serialization.Json.JsonClassDataContract.ReadJsonValueCore(XmlReaderDelegator jsonReader, XmlObjectSerializerReadContextComplexJson context)
   at System.Runtime.Serialization.Json.JsonDataContract.ReadJsonValue(XmlReaderDelegator jsonReader, XmlObjectSerializerReadContextComplexJson context)
   at System.Runtime.Serialization.Json.XmlObjectSerializerReadContextComplexJson.ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, ref DataContract dataContract)
   at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
   at ReadLFromJson(XmlReaderDelegator, XmlObjectSerializerReadContextComplexJson, XmlDictionaryString, XmlDictionaryString[])
   at System.Runtime.Serialization.Json.JsonClassDataContract.ReadJsonValueCore(XmlReaderDelegator jsonReader, XmlObjectSerializerReadContextComplexJson context)
   at System.Runtime.Serialization.Json.JsonDataContract.ReadJsonValue(XmlReaderDelegator jsonReader, XmlObjectSerializerReadContextComplexJson context)
   at System.Runtime.Serialization.Json.XmlObjectSerializerReadContextComplexJson.ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, ref DataContract dataContract)
   at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, DataContract dataContract, String name, String ns)
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName)
   at System.Runtime.Serialization.XmlObjectSerializer.InternalReadObject(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject(XmlDictionaryReader reader)
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject(Stream stream)
   at Serialize.Linq.Serializers.DataSerializer.Deserialize(Stream stream) in DataSerializer.cs: line 50
   at Serialize.Linq.Serializers.TextSerializer.Deserialize(String text) in TextSerializer.cs: line 40
   at Serialize.Linq.Serializers.ExpressionSerializer.DeserializeText(String text) in ExpressionSerializer.cs: line 53
   at Serialize.Linq.Tests.ExpressionDeserializationIssues.Deserialize_expression_with_guid_constant() in ExpressionDeserializationIssues.cs: line 19

Inheritance Deserialization

Three objects, base class named, Debtor (abstract which has a few properties one being Id), IndividualDebtor & CompanyDebtor which inherit from the Debtor class.

I can serialize and deserialize the object(s) just fine untill I start filtering based on a property from the base class, in my case Id.

I get the following exception;

An exception of type 'System.ArgumentException' occurred in System.Core.dll but was not handled in user code

Additional information: Property 'Int32 Id' is not defined for type 'Cms.Entities.Models.IndividualDebtor'

Which made me confused since why would a property have the name 'Int32 Id', So I looked at the json string which was produced (in the interest of completion I also added the expression for the a property which is defined on the IndividualDebtor class, both strings look very similar for me, including the 'signature' which starts with the type in both cases.

{"__type":"LambdaExpressionNode:#Serialize.Linq.Nodes","NodeType":18,"Type":{"GenericArguments":[{"Name":"Cms.Messages.Dto.IndividualDebtor"},{"Name":"System.Boolean"}],"Name":"System.Func`2"},"Body":{"__type":"MemberExpressionNode:#Serialize.Linq.Nodes","NodeType":23,"Type":{"Name":"System.Boolean"},"Expression":{"__type":"MemberExpressionNode:#Serialize.Linq.Nodes","NodeType":23,"Type":{"GenericArguments":[{"Name":"System.DateTime"}],"Name":"System.Nullable`1"},"Expression":{"__type":"ParameterExpressionNode:#Serialize.Linq.Nodes","NodeType":38,"Type":{"Name":"Cms.Messages.Dto.IndividualDebtor"},"Name":"d"},"Member":{"DeclaringType":{"Name":"Cms.Messages.Dto.IndividualDebtor"},"Signature":"System.Nullable`1[System.DateTime] DateOfBirth"}},"Member":{"DeclaringType":{"GenericArguments":[{"Name":"System.DateTime"}],"Name":"System.Nullable`1"},"Signature":"Boolean HasValue"}},"Parameters":[{"__type":"ParameterExpressionNode:#Serialize.Linq.Nodes","NodeType":38,"Type":{"Name":"Cms.Messages.Dto.IndividualDebtor"},"Name":"d"}]}
{"__type":"LambdaExpressionNode:#Serialize.Linq.Nodes","NodeType":18,"Type":{"GenericArguments":[{"Name":"Cms.Messages.Dto.IndividualDebtor"},{"Name":"System.Boolean"}],"Name":"System.Func`2"},"Body":{"__type":"BinaryExpressionNode:#Serialize.Linq.Nodes","NodeType":13,"Type":{"Name":"System.Boolean"},"Left":{"__type":"MemberExpressionNode:#Serialize.Linq.Nodes","NodeType":23,"Type":{"Name":"System.Int32"},"Expression":{"__type":"ParameterExpressionNode:#Serialize.Linq.Nodes","NodeType":38,"Type":{"Name":"Cms.Messages.Dto.IndividualDebtor"},"Name":"d"},"Member":{"DeclaringType":{"Name":"Cms.Messages.Dto.Debtor"},"Signature":"Int32 Id"}},"Method":{},"Right":{"__type":"ConstantExpressionNode:#Serialize.Linq.Nodes","NodeType":9,"Type":{"Name":"System.Int32"},"Value":2}},"Parameters":[{"__type":"ParameterExpressionNode:#Serialize.Linq.Nodes","NodeType":38,"Type":{"Name":"Cms.Messages.Dto.IndividualDebtor"},"Name":"d"}]}

Maybe I'm doing something horribly wrong since It seems odd to me that i'd be the first to try this with some form of inheritance. If any more information (like code snippets) are required I'd be more than happy to add those.

Serializing an expression conaining Enums results in an SerializatonException

When an expression references contains an enum variable, serialization throws a SerializationException. This is illustrated by this unit test:

    [TestMethod]
    public void SerializeLambdaWithEnumTest()
    {
        foreach (var textSerializer in new ITextSerializer[] { new JsonSerializer(), new XmlSerializer() })
        {
            var serializer = new ExpressionSerializer(textSerializer);
            var fish = new[]
            {
                new ItemWithEnum {Gender = Gender.Male},
                new ItemWithEnum {Gender = Gender.Female},
                new ItemWithEnum(),
                new ItemWithEnum {Gender = Gender.Female}
            };
            var some = Gender.Female;
            Expression<Func<ItemWithEnum, bool>> expectedExpression = f => f.Gender == some;
            var expected = fish.Where(expectedExpression.Compile()).Count();

            var serialized = serializer.SerializeText(expectedExpression); // throws SerializationException
            var actualExpression = (Expression<Func<ItemWithEnum, bool>>)serializer.DeserializeText(serialized);
            var actual = fish.Where(actualExpression.Compile()).Count();

            Assert.AreEqual(expected, actual);
        }
    }

    private class ItemWithEnum
    {
        public Gender Gender { get; set; } 
    }

    private enum Gender
    {
        Male,
        Female
    }

n.b.
If the enum is referenced inline, everything works:

    Expression<Func<ItemWithEnum, bool>> expectedExpression = f => f.Gender == Gender.Female; // this works

Closures with nulllables do not get serialized correctly.

Closures with nulllables loose do not get serialized correctly. The implicit conversion to nullable is dropped, so when attempting to deserialize an exception occurs.

this fails with not equal:

    [TestMethod]
    public void SerializeDeserializeLambdaWithNullableTest()
    {
        foreach (var textSerializer in new ITextSerializer[] { new JsonSerializer(), new XmlSerializer() })
        {
            var serializer = new ExpressionSerializer(textSerializer);
            string actual;
            string expected;
            {
                int seven = 7;
                Expression<Func<Fish, bool>> expectedExpression = f => f.Count == seven;
                expected = serializer.SerializeText(expectedExpression);
            }

            {
                int? seven = 7;
                Expression<Func<Fish, bool>>  actualExpression = f => f.Count == seven;
                actual = serializer.SerializeText(actualExpression);
            }

            Assert.AreEqual(expected, actual);
        }
    }

This fails with an exception:

    [TestMethod]
    public void SerializeLambdaWithNullableTest()
    {
        foreach (var textSerializer in new ITextSerializer[] { new JsonSerializer(), new XmlSerializer() })
        {
            var serializer = new ExpressionSerializer(textSerializer);
            var fish = new[]
            {
                new Fish {Count = 0},
                new Fish {Count = 1},
                new Fish(),
                new Fish {Count = 1}
            };
            int? count = 1;
            Expression<Func<Fish, bool>> expectedExpression = f => f.Count == count;
            var expected = fish.Where(expectedExpression.Compile()).Count();

            var serialized = serializer.SerializeText(expectedExpression);
            var actualExpression = (Expression<Func<Fish, bool>>)serializer.DeserializeText(serialized);
            var actual = fish.Where(actualExpression.Compile()).Count();

            Assert.AreEqual(expected, actual);
        }
    }

Processing Linq expressions may cause exceptions

Somehow, I experience a couple of tests failing.

It occures when a Linq expression is processed:

Expression<Func<IEnumerable<int>, IEnumerable<int>>> interferingExpression = 
c =>  from x in c
         let anotherConst = 100
         where (x == anotherConst)
         select x;

"Where" predicate is pushed into an anonymous class by a compiler, and finally ExpressionContext.ResolveType may find a wrong anonymous class (from another assembly for example) and fail to procceed further due to the mismatch.

PublicInstancePropertiesAssert.AreEqual method is implemented and used incorrectly

I've stumbled upon this issue while investigating TypeBinaryExpressionNode serialization bug. ExpressionNode tests don't work at all due to the wrong implementation of PublicInstancePropertiesAssert.AreEqual helper method.

There are a couple of issues with this method:

  1. It only looks into the one level of properties, while expression trees may consist of multiple levels of nodes (e.g. binary expression nodes) which properties must be compared also.
  2. It uses Assert.AreEqual for every property. This leads to a wrong comparation result in the case of reference type properties as we are working with two separate expression trees.
    3. The way this method is called forces it to compare every given expression as a System.Linq.Expressions.Expression class instance. Thus it only goes through 3 base class properties and considers nearly every pair of expressions as equal. That's why all tests are passed regardless of the real situation.

Version Mismatch

Is there a way to relax or for me to override version checking behavior on the DTO assembly when de-serializing? I have a client that uses a slightly different version of the DTO than the server. They are completely compatible, but when Serialize.Linq is being invoked on the server-side, it complains about not being able to find the DTO assembly due to version number difference.

Thanks for this library. It is making my job easier and more fun.

Collection serialization expression 'contains'

So unless I am doing something wrong, this looks like it's the same issue assafw is seeing (#53 below). I have the following:

            var enterpriseKeys = new List<long?> { 1, 2, 3, 4 };

            var predicatePart =
                (Expression<Func<GroupEntity, bool>>)
                (groupType =>
                 enterpriseKeys.Contains(groupType.GroupEnterpriseKey));

            var serializeTo = new ExpressionSerializer(new XmlSerializer());
            var predicatePartSerializedToString = serializeTo.SerializeText(predicatePart);

I get the error as follows:

Error converting type: Type 'System.Collections.Generic.List1[[System.Nullable1[[System.Int64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]' with data contract name 'ArrayOfNullableOflong:http://schemas.datacontract.org/2004/07/System' is not expected.

Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.

SerializationExeption - Simple DateTime expression.

This expression {(left.DayOfWeek == Monday)} will give an exception:

"Type 'System.DayOfWeek' with data contract name 'DayOfWeek:http://schemas.datacontract.org/2004/07/System' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer."

If I convert it first I can avoid the error.

{(left.DayOfWeek == Monday)} // Doesn't work

{(ConvertChecked(left.DayOfWeek) == ConvertChecked(Monday))} // Doesn't work

{(ConvertChecked(d.DayOfWeek) == 0)} // Does work

EDIT: Serializing to binary if that matters.

Use deserialized Expression against IQueryable...

I have One Question, maybe yu can Help me:

I have this on the Client Side:

var expression = (Expression<Func<ImageDTO, bool>>)(x => x.Name == "Miller");
var expressionNode = expression.ToExpressionNode();
var jj = CommonClient.Instance.MainCommonService.Channel.GetImages(expressionNode);

and on the Server side I have a IQueryable List of ImageDTO Objects. Is it possible to run the Expression against this List??

serialization issues

This is a great utility and i'd love to make it work for me.

My first test was this simple predicate

  var arr = new string[] {"one","two"}; // initially this was a List<string> but couldn't make it work with serializer
  var results = new myObj<MyType>().Where(x => arr.Contains(x.Code) && x.Date >= dateFrom);

if arr is List I was getting a ton of issues complaining about serialization of List and ArrayOfString.

I noticed that I can do this

  var bs = new BinarySerializer();
  bs.AddKnownType(typeof(string[]));

whenever I tried adding List as a known type it would always complain that it either exists, or there was a conflict with List + Array being added together. So the only way I could make it work was registering known type string[] and using only this in my predicate.

the outcome however looks like this

x => (value(System.String[]).Contains(x.Code) AndAlso ...

as you see it only calls ToString on the Array, and contents are not shown.

License issue

GPL requires that every file in your project has a license preamble.

So I guess you can add license to every file or change it to something saner (like BSD) :)

Regards,
Rikard

Bug when creating structs

Hi,

I stumbled upon a problem when trying to generate an ExpressionNode for an expression which creates a struct. Here's an example:

using Serialize.Linq.Extensions;
using Serialize.Linq.Nodes;
using System.Linq.Expressions;

namespace Repro
{
    struct Repro
    {
    }

    class Program
    {
        static void Main(string[] args)
        {
            Expression<Func<Repro>> expr = () => new Repro();

            var node = expr.ToExpressionNode();
            var expr2 = node.ToExpression<Func<Repro>>();
        }
    }
}

The problem seems to be in NewExpressionNode.cs, I assume wanted to cover this case by checking for this.Constructor == null but actually it can never be null.

the binary operator LessThan is not defined for the types int32 and nullable int32

ExpressionNode.ToExpression fails with an InvalidOperationException when comparing an int to a nullable int. Below is a test for this. Making p.Id a nullable int and the parameter an int also fails.

[TestMethod]
public void SerializeDeserializeBinaryIntToParameterNullableIntComparisonTest()
{
foreach (var binSerializer in CreateBinarySerializers())
{
var serializer = new ExpressionSerializer(binSerializer);

            int? nullableInt = 5;
            var expected = (System.Linq.Expressions.Expression<System.Func<Bar, bool>>)(p => p.Id < nullableInt);

            var bytes = serializer.SerializeBinary(expected);
            this.TestContext.WriteLine("{0} serializes to bytes with length {1}", expected, bytes.Length);

            var actual = (System.Linq.Expressions.Expression<System.Func<Bar, bool>>)serializer.DeserializeBinary(bytes);
            Assert.IsNotNull(actual, "Input expression was {0}, but output is null for '{1}'", expected, binSerializer.GetType());
        }
    }

Can you mark the *Node classes as serializable

Can you mark the *Node classes as [Serializable]? That will allow to use them in the Binary Formatter, for example in ,NET Remoting.

I've tried this with local sources and it works pretty well.

P.S.
Factory that you have in base node class needs to be marked as [NonSerialized]

Change type of expression when deserializing

Scenario:

  • expression is built based on DTO type
  • DTO has same shape as entity (or is a subset of entity properties)
  • DTO is sent to the server

Now I want to deserialize expression and have the func executed over the my domain entity.

I got it working with serializing to json and doing a
string.Replace(typeof(DTO).FullName, typeof(Entity).FullName)

Is it the only way to achieve it?
Any pitfalls I may run in?

Thanks

Deerializing an expression conaining a UTC Date results in an Exception

regular dates serialize into something like Date(123123123123+0100).
UTC dates (like DateTime.UtcNow) serialize into something like Date(123123123123).

This can be fixed by changing the regular expression in ValueConverter.cs to:

    private static readonly Regex _dateRegex = new Regex(@"/Date\((\d+)(([-+])(\d+))?\)/"

if !SILVERLIGHT

        ,RegexOptions.Compiled

endif

        );

Unit test:

    [TestMethod]
    public void SerializeWithDateTimeTest()
    {
        foreach (var textSerializer in new ITextSerializer[] { new JsonSerializer(), new XmlSerializer() })
        {
            var serializer = new ExpressionSerializer(textSerializer);
            var fish = new[]
            {
                new Yarr {Date = new DateTime(3000,1,1)},
                new Yarr {Date = new DateTime(2000,1,1)},
                new Yarr(),
                new Yarr { Date = DateTime.Now.AddYears(1) }
            };
            var date = DateTime.UtcNow;
            Expression<Func<Yarr, bool>> expectedExpression = f => f.Date > date;
            var expected = fish.Where(expectedExpression.Compile()).Count();

            var serialized = serializer.SerializeText(expectedExpression);
            var actualExpression = (Expression<Func<Yarr, bool>>)serializer.DeserializeText(serialized);
            var actual = fish.Where(actualExpression.Compile()).Count();

            Assert.AreEqual(expected, actual);
        }
    }

    public class Yarr
    {
        public DateTime Date { get; set; }
    }

How Can I .Deserialize Expression<Func<T, dynamic>>

I have a Expression :
Expression<Func<T, dynamic>> exp=s => new { s.Name, s.ProductCategoryID }
serialize it to string . But When I deserialize this string ,it retun null with error " 序列不包含任何匹配元素"
The seialize string is QA5FeHByZXNzaW9uTm9kZS4EdHlwZZgUTGFtYmRhRXhwcmVzc2lvbk5vZGUIPGh0dHA6Ly9zY2hlbWFzLmRhdGFjb250cmFjdC5vcmcvMjAwNC8wNy9TZXJpYWxpemUuTGlucS5Ob2RlcwkBaSlodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZUAITm9kZVR5cGWZBkxhbWJkYUAEVHlwZUAQR2VuZXJpY0FyZ3VtZW50c0AIVHlwZU5vZGVABE5hbWWZHUNsYXNzTGlicmFyeTEuUHJvZHVjdENhdGVnb3J5AUAIVHlwZU5vZGVABE5hbWWZDVN5c3RlbS5PYmplY3QBAUAETmFtZZkNU3lzdGVtLkZ1bmNgMgFABEJvZHkuBHR5cGWYEU5ld0V4cHJlc3Npb25Ob2RlQAhOb2RlVHlwZZkDTmV3QARUeXBlQBBHZW5lcmljQXJndW1lbnRzQAhUeXBlTm9kZUAETmFtZZkNU3lzdGVtLlN0cmluZwFACFR5cGVOb2RlQAROYW1lmQxTeXN0ZW0uSW50MzIBAUAETmFtZZkVPD5mX19Bbm9ueW1vdXNUeXBlMGAyAUAJQXJndW1lbnRzQA5FeHByZXNzaW9uTm9kZS4EdHlwZZgUTWVtYmVyRXhwcmVzc2lvbk5vZGVACE5vZGVUeXBlmQxNZW1iZXJBY2Nlc3NABFR5cGVABE5hbWWZDVN5c3RlbS5TdHJpbmcBQApFeHByZXNzaW9uLgR0eXBlmBdQYXJhbWV0ZXJFeHByZXNzaW9uTm9kZUAITm9kZVR5cGWZCVBhcmFtZXRlckAEVHlwZUAETmFtZZkdQ2xhc3NMaWJyYXJ5MS5Qcm9kdWN0Q2F0ZWdvcnkBQAROYW1lmQFzAUAGTWVtYmVyQA1EZWNsYXJpbmdUeXBlQAROYW1lmR1DbGFzc0xpYnJhcnkxLlByb2R1Y3RDYXRlZ29yeQFACk1lbWJlclR5cGWZCFByb3BlcnR5QAlTaWduYXR1cmWZElN5c3RlbS5TdHJpbmcgTmFtZQEBQA5FeHByZXNzaW9uTm9kZS4EdHlwZZgUTWVtYmVyRXhwcmVzc2lvbk5vZGVACE5vZGVUeXBlmQxNZW1iZXJBY2Nlc3NABFR5cGVABE5hbWWZDFN5c3RlbS5JbnQzMgFACkV4cHJlc3Npb24uBHR5cGWYF1BhcmFtZXRlckV4cHJlc3Npb25Ob2RlQAhOb2RlVHlwZZkJUGFyYW1ldGVyQARUeXBlQAROYW1lmR1DbGFzc0xpYnJhcnkxLlByb2R1Y3RDYXRlZ29yeQFABE5hbWWZAXMBQAZNZW1iZXJADURlY2xhcmluZ1R5cGVABE5hbWWZHUNsYXNzTGlicmFyeTEuUHJvZHVjdENhdGVnb3J5AUAKTWVtYmVyVHlwZZkIUHJvcGVydHlACVNpZ25hdHVyZZkXSW50MzIgUHJvZHVjdENhdGVnb3J5SUQBAQFAC0NvbnN0cnVjdG9yQA1EZWNsYXJpbmdUeXBlQBBHZW5lcmljQXJndW1lbnRzQAhUeXBlTm9kZUAETmFtZZkNU3lzdGVtLlN0cmluZwFACFR5cGVOb2RlQAROYW1lmQxTeXN0ZW0uSW50MzIBAUAETmFtZZkVPD5mX19Bbm9ueW1vdXNUeXBlMGAyAUAKTWVtYmVyVHlwZZkLQ29uc3RydWN0b3JACVNpZ25hdHVyZZkgVm9pZCAuY3RvcihTeXN0ZW0uU3RyaW5nLCBJbnQzMikBQAdNZW1iZXJzQA5NZW1iZXJJbmZvTm9kZUANRGVjbGFyaW5nVHlwZUAQR2VuZXJpY0FyZ3VtZW50c0AIVHlwZU5vZGVABE5hbWWZDVN5c3RlbS5TdHJpbmcBQAhUeXBlTm9kZUAETmFtZZkMU3lzdGVtLkludDMyAQFABE5hbWWZFTw+Zl9fQW5vbnltb3VzVHlwZTBgMgFACk1lbWJlclR5cGWZCFByb3BlcnR5QAlTaWduYXR1cmWZElN5c3RlbS5TdHJpbmcgTmFtZQFADk1lbWJlckluZm9Ob2RlQA1EZWNsYXJpbmdUeXBlQBBHZW5lcmljQXJndW1lbnRzQAhUeXBlTm9kZUAETmFtZZkNU3lzdGVtLlN0cmluZwFACFR5cGVOb2RlQAROYW1lmQxTeXN0ZW0uSW50MzIBAUAETmFtZZkVPD5mX19Bbm9ueW1vdXNUeXBlMGAyAUAKTWVtYmVyVHlwZZkIUHJvcGVydHlACVNpZ25hdHVyZZkXSW50MzIgUHJvZHVjdENhdGVnb3J5SUQBAQFAClBhcmFtZXRlcnNADkV4cHJlc3Npb25Ob2RlLgR0eXBlmBdQYXJhbWV0ZXJFeHByZXNzaW9uTm9kZUAITm9kZVR5cGWZCVBhcmFtZXRlckAEVHlwZUAETmFtZZkdQ2xhc3NMaWJyYXJ5MS5Qcm9kdWN0Q2F0ZWdvcnkBQAROYW1lmQFzAQEB

svcutil compatibility and minor bugs

First, thank you for this great library! It's really terrific!!!

In ConditionalExpressionNode.cs the attribute
[DataMember(EmitDefaultValue = false, Name = "T")] on property
public ExpressionNode Test { get; set; }
conflicts with the same attribute on property ExpressionNode.Type.
Eg. ...Name = "C" as "Condition" could be a solution.

In PropertyInfoNodes.cs there is a

if SERIALIZE_LINQ_WITH_LONG_DATA_NAMES

instead of

if !SERIALIZE_LINQ_OPTIMIZE_SIZE

WARNING: Modifying it breaks backward compatibility with current services, DataContract name changes from "PI" to "PropertyInfoNode"!!!

The "long" DataContract names of MemberNode<> and ExpressionNode<> abstract generic classes should be specified, because svcutil generates "funny" names like ExpressionNodeOfLambdaExpressionQsd8_SODT. And recreates these abstract classes as non-abstract classes during proxy generation (metadata doesn't support abstract). Even when specifying the reference to Serialize.Linq.dll. With "long" DataContract name specified, only one useless non-abstract class should be deleted from the generated proxy.
Eg. [DataContract(Name = "MemberNodeGeneric")] and [DataContract(Name = "ExpressionNodeGeneric")] could be a solution.

Does not work with related objects

Hi,
My objective is to serialize Expression Trees. The library works as a charm when we write expressions on an object, but when we add expression for a related IQueryable() object, we get "Expression not allowed" exception.

for e.g. We have following classes

    public class Order
    {
        public virtual int Id { get; set; }
        public virtual int qty { get; set; }
    }
    public class Document
    {
        public virtual int Id { get; set; }
        public virtual ICollection<Order> Orders { get; set; }
    }

      //i want to query Document object based on related object Order with below expression
        Expression<Func<Order, bool>> predicate = x => x.Id > 0 && x.Id < 5;

        Expression<Func<Document, bool>> pred = x => x.Orders.AsQueryable().Any(predicate);

        var serializer = new ExpressionSerializer(new BinarySerializer());
        var value = serializer.SerializeBinary(pred);

The last line above resulted in error "Expression not allowed"

Thanks
Syed

Serialize and deserialize anonymous types

Much like the process used to project dto's from their source type I would like to be able to project anonymous types over the wire (wcf) and process the expression in the select portion of my query against the data source. I am having trouble deserialize the expression on the server.

screenshot_1

Serialize from Expression to String. Using instances value in the predicate.

Dear Colleague,

Please, see this example:

class MyEntity
{
    public string Name { get; set; }
}

...
Expression<Func<MyEntity, bool>> where = x => x.Name == "Peter";
var exp = where.ToExpressionNode().ToString();
Console.WriteLine(exp);
...

The output is perfect, like this: "x => (x.Name == "Peter")"
However, if we change a little bit, the result is different, see:

...
var obj = new MyEntity {Name = "Peter"};
Expression<Func<MyEntity, bool>> where = x => x.Name == obj.Name;
var exp = where.ToExpressionNode().ToString();
Console.WriteLine(exp);
...

And the output is: "x => (x.Name == value(ConsoleApplication1.MyEntity).Name)"
Any chances here to get the same result as the first example?

Thanks in advance for your support.
Marcel

Deserializing expression with constant DateTime using JsonSerializer

It's more FYI than a real issue as I feel that's the problem of JsonSerializer and more precisely of NetDataContractJsonSerializer so it cannot be easily fixed. If so, just close this issue, it will remain here as a 'FYI' or for further reference.

The test:

[TestMethod]
public void Expression_with_constant_date_time_json()
{
    var constant = Expression.Constant(DateTime.Today);

    var serializer = new ExpressionSerializer(new JsonSerializer());

    var serialized = serializer.SerializeText(constant);
    var deserialized = serializer.DeserializeText(serialized);
    ExpressionAssert.AreEqual(constant, deserialized);
}

Test is failing at deserialization. Failure details:

System.MissingMethodException: Constructor on type 'System.DateTime' not found.
    at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, ref StackCrawlMark stackMark)
   at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   at System.Activator.CreateInstance(Type type, Object[] args)
   at Serialize.Linq.Internals.ValueConverter.Convert(Object value, Type type) in ValueConverter.cs: line 24
   at Serialize.Linq.Nodes.ConstantExpressionNode.set_Value(Object value) in ConstantExpressionNode.cs: line 76
   at ReadCFromJson(XmlReaderDelegator, XmlObjectSerializerReadContextComplexJson, XmlDictionaryString, XmlDictionaryString[])
   at System.Runtime.Serialization.Json.JsonClassDataContract.ReadJsonValueCore(XmlReaderDelegator jsonReader, XmlObjectSerializerReadContextComplexJson context)
   at System.Runtime.Serialization.Json.JsonDataContract.ReadJsonValue(XmlReaderDelegator jsonReader, XmlObjectSerializerReadContextComplexJson context)
   at System.Runtime.Serialization.Json.XmlObjectSerializerReadContextComplexJson.ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, ref DataContract dataContract)
   at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, DataContract dataContract, String name, String ns)
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName)
   at System.Runtime.Serialization.XmlObjectSerializer.InternalReadObject(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject(XmlDictionaryReader reader)
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject(Stream stream)
   at Serialize.Linq.Serializers.DataSerializer.Deserialize(Stream stream) in DataSerializer.cs: line 51

Two other serializers, XML and Binary, are passing this test.

incorrect serialization of TypeBinaryExpression node

Hi, I'm using Serialize.Linq on some weird expression trees and I've found a bug. This tree:
{null.Where(entity => ((entity TypeEqual Farm) AndAlso Convert(entity.Animals).Any()}
deserializes as this non-equivalent tree:
{null.Where(entity => ((entity Is Farm) AndAlso Convert(entity.Animals).Any()}

The TypeEqual has become an Is, representing an assignability check instead of an equality check. I believe the issue is in https://github.com/esskar/Serialize.Linq/blob/master/src/Serialize.Linq/Nodes/TypeBinaryExpressionNode.cs - it does not check the NodeType, and unconditionally deserialises to Expression.TypeIs.

Here's a pull request which hopefully contains the fix: #60

expressions with conjunctions fail after binary serialization

This failing test is similar to the SerializeDeserializeBinaryTest. It illustrates an issue that I have encountered after serializing an expression with a conjunction using WCF datacontract serialization. The lambda expression compile method succeeds before the serialization but not after. The lambda expression compile method error is similar to the error I receive after WCF datacontract serialization.

    [TestMethod]
    public void SerializeDeserializeBinaryComplexExpressionWithCompileTest()
    {
        foreach (var binSerializer in CreateBinarySerializers())
        {
            var serializer = new ExpressionSerializer(binSerializer);

            //var expected = (System.Linq.Expressions.Expression<System.Func<Bar, bool>>)(p => p.LastName == "Miller");  // this expresion is ok

            var expected = (System.Linq.Expressions.Expression<System.Func<Bar, bool>>)(p => p.LastName == "Miller" && p.FirstName.StartsWith("M"));

            var compiledExpression = expected.Compile();

            var bytes = serializer.SerializeBinary(expected);

            this.TestContext.WriteLine("{0} serializes to bytes with length {1}", expected, bytes.Length);

            var actual = (System.Linq.Expressions.Expression<System.Func<Bar, bool>>)serializer.DeserializeBinary(bytes);

            Assert.IsNotNull(actual, "Input expression was {0}, but output is null for '{1}'", expected, binSerializer.GetType());
            ExpressionAssert.AreEqual(expected, actual);

            var compiledExpressionAfterSerialization = actual.Compile();
        }
    }

WebAPI ExpressionNode NULL

Hi esskar! Here my code that you asked for in the blog:

[HttpGet]
public ExpressionNode Get(string firstName)
{
       return ((Expression<Func<ContactModel, bool>>)
                            (m => m.FirstName == firstName)).ToExpressionNode();
}

Returns this JSON:

{
    "Body":
    {
        "Left":
        {
            "Expression":
            {
                "Name": "m",
                "NodeType": 38,
                "Type":
                {
                    "Name": "ClientTrackerWebAPI.ContactModel"
                }
            },
            "Member":
            {
                "DeclaringType":
                {
                    "Name": "ClientTrackerWebAPI.ContactModel"
                },
                "MemberType": 16,
                "Signature": "System.String FirstName"
            },
            "NodeType": 23,
            "Type":
            {
                "Name": "System.String"
            }
        },
        "Method":
        {
            "DeclaringType":
            {
                "Name": "System.String"
            },
            "MemberType": 8,
            "Signature": "Boolean op_Equality(System.String, System.String)"
        },
        "Right":
        {
            "Type":
            {
                "Name": "System.String"
            },
            "Value": "Miles",
            "NodeType": 9
        },
        "NodeType": 13,
        "Type":
        {
            "Name": "System.Boolean"
        }
    },
    "Parameters":
    [
        {
            "Name": "m",
            "NodeType": 38,
            "Type":
            {
                "Name": "ClientTrackerWebAPI.ContactModel"
            }
        }
    ],
    "NodeType": 18,
    "Type":
    {
        "Name": "System.Func`2",
        "GenericArguments":
        [
            {
                "Name": "ClientTrackerWebAPI.ContactModel"
            },
            {
                "Name": "System.Boolean"
            }
        ]
    }
}

Looks good so far. And the i send that into:

[HttpGet]
public List<ContactModel> GetByProperty([FromBody]ExpressionNode expressionNode)
{
    return ContactModelSqlService.Find(expressionNode);
}

Any ideas why expressionNode is null?

//Billy

Serialization over NServiceBus; System.MemberAccessException: Cannot create an abstract class.

This might ben more of an issue in NServiceBus than in Serialize.Linq, not entirely sure but I'll post it here regardless.

When attempting to make a call over NServiceBus where we've created a Message with in it a Property of the type ExpressionNode the message seems to get serialized perfectly fine. However on the service end when Deserializing we get the following exception;

ERROR NServiceBus.Unicast.Transport.TransportReceiver Failed to deserialize message with ID: c6e85a3a-ed9f-4211-809f-a44500d99727
NServiceBus.MessageDeserializationException: An error occurred while attempting to extract logical messages from transport message c6e85a3a-ed9f-4211-809f-a44500d99727 ---> System.MemberAccessException: Cannot create an abstract class.
at System.Runtime.Serialization.FormatterServices.nativeGetUninitializedObject(RuntimeType type)
at NServiceBus.MessageInterfaces.MessageMapper.Reflection.MessageMapper.CreateInstance(Type t) in c:\BuildAgent\work\1b05a2fea6e4cd32\src\NServiceBus.Core\MessageInterfaces\MessageMapper\Reflection\MessageMapper.cs:line 426

This even happens if we instead of an ExpressionNode require a LambaExpressionNode (which is the underlying type generated by .ToExpressionNode();

Any ideas at all? Should I be bugging the guys @ NServiceBus instead since there is a fault on their end?

FYI what we want to accomplish is a 'RefinedQuery' Object with a Take, Skip, Where and OrderBy property. In order to allow the clients to filter their screens. The Take and Skip will simply be integer values, the OrderBy I've yet to wrap my head around and the Where property I'd like to use the ExpressionNode to allow for nice hardcoded filtering on the client side.

ToExpressionNode Extension method breaks in some cases

Exception details:

System.InvalidOperationException was caught
  Message=variable 'mt' of type 'Program+MyType' referenced from scope '', but it is not defined
  Source=System.Core
  StackTrace:
       at System.Linq.Expressions.Compiler.VariableBinder.Reference(ParameterExpression node, VariableStorageKind storage)
       at System.Linq.Expressions.Compiler.VariableBinder.VisitParameter(ParameterExpression node)
       at System.Linq.Expressions.ParameterExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at System.Linq.Expressions.ExpressionVisitor.VisitMember(MemberExpression node)
       at System.Linq.Expressions.MemberExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at System.Linq.Expressions.ExpressionVisitor.VisitArguments(IArgumentProvider nodes)
       at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
       at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at System.Linq.Expressions.ExpressionVisitor.Visit(ReadOnlyCollection`1 nodes)
       at System.Linq.Expressions.Compiler.VariableBinder.VisitLambda[T](Expression`1 node)
       at System.Linq.Expressions.Expression`1.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at System.Linq.Expressions.Compiler.LambdaCompiler.Compile(LambdaExpression lambda, DebugInfoGenerator debugInfoGenerator)
       at System.Linq.Expressions.LambdaExpression.Compile()
       at Serialize.Linq.Factories.TypeResolverNodeFactory.ResolveMethodCallExpression(MethodCallExpression methodCallExpression) in C:\Users\myname\Desktop\esskar-Serialize.Linq-91b9b93\esskar-Serialize.Linq-91b9b93\src\Serialize.Linq\Factories\TypeResolverNodeFactory.cs:line 89
       at Serialize.Linq.Factories.TypeResolverNodeFactory.Create(Expression expression) in C:\Users\myname\Desktop\esskar-Serialize.Linq-91b9b93\esskar-Serialize.Linq-91b9b93\src\Serialize.Linq\Factories\TypeResolverNodeFactory.cs:line 104
       at Serialize.Linq.Nodes.LambdaExpressionNode.Initialize(LambdaExpression expression) in C:\Users\myname\Desktop\esskar-Serialize.Linq-91b9b93\esskar-Serialize.Linq-91b9b93\src\Serialize.Linq\Nodes\LambdaExpressionNode.cs:line 41
       at Serialize.Linq.Nodes.ExpressionNode`1..ctor(INodeFactory factory, TExpression expression) in C:\Users\myname\Desktop\esskar-Serialize.Linq-91b9b93\esskar-Serialize.Linq-91b9b93\src\Serialize.Linq\Nodes\ExpressionNode.cs:line 20
       at Serialize.Linq.Nodes.LambdaExpressionNode..ctor(INodeFactory factory, LambdaExpression expression) in C:\Users\myname\Desktop\esskar-Serialize.Linq-91b9b93\esskar-Serialize.Linq-91b9b93\src\Serialize.Linq\Nodes\LambdaExpressionNode.cs:line 18
       at Serialize.Linq.Factories.NodeFactory.Create(Expression expression) in C:\Users\myname\Desktop\esskar-Serialize.Linq-91b9b93\esskar-Serialize.Linq-91b9b93\src\Serialize.Linq\Factories\NodeFactory.cs:line 19
       at Serialize.Linq.Factories.TypeResolverNodeFactory.Create(Expression expression) in C:\Users\myname\Desktop\esskar-Serialize.Linq-91b9b93\esskar-Serialize.Linq-91b9b93\src\Serialize.Linq\Factories\TypeResolverNodeFactory.cs:line 105
       at Serialize.Linq.Factories.DefaultNodeFactory.Create(Expression expression) in C:\Users\myname\Desktop\esskar-Serialize.Linq-91b9b93\esskar-Serialize.Linq-91b9b93\src\Serialize.Linq\Factories\DefaultNodeFactory.cs:line 33
       at Serialize.Linq.Serializers.ExpressionConverter.Convert(Expression expression) in C:\Users\myname\Desktop\esskar-Serialize.Linq-91b9b93\esskar-Serialize.Linq-91b9b93\src\Serialize.Linq\Serializers\ExpressionConverter.cs:line 14
       at Serialize.Linq.Extensions.ExpressionExtensions.ToExpressionNode(Expression expression) in C:\Users\myname\Desktop\esskar-Serialize.Linq-91b9b93\esskar-Serialize.Linq-91b9b93\src\Serialize.Linq\Extensions\ExpressionExtensions.cs:line 17
       at Program.Main(String[] args) in C:\Users\myname\Documents\Visual Studio 2010\Projects\Sandbox\ConsoleSandbox\Program.cs:line 89
  InnerException: 

Code to duplicate:

public class MyType
{
    public int Id { get; set; }
}
var ids = new List<int> { 1, 2, 3, 4, 5, 6 };
Expression<Func<MyType, bool>> expression1 = mt => mt.Id == 5;
var node1 = expression1.ToExpressionNode();

Expression<Func<MyType, bool>> expression2 = mt => ids.Contains(mt.Id);
var node2 = expression2.ToExpressionNode();

The line of code that breaks is var node2 = expression2.ToExpressionNode();. Obviously, the reason is the ids.Contains(mt.Id) in the expression I made. I would love to be able to use .Contains in my expressions, but understand there's a lot going on in this library.

Thanks!

Sequence contains more than one matching element

I am using version 1.2.1 of Serialize.Linq. When I try the following construct, calling ToExpressionNode() causes an InvalidOperationException to be thrown:

var feb1 = new DateTime(2015, 2, 1);
var feb15 = new DateTime(2015, 2, 15);
Expression<Func<DataPoint, bool>> expr =
    dp => dp.Timestamp >= feb1 && dp.Timestamp < feb15 && dp.AcctId == 1;
var exprNode = expr.ToExpressionNode();

The error message is:

Sequence contains more than one matching element

The relevant stack trace is provided below. However, note that if I remove the dp.Timestamp < feb15 condition from the expression, then calling ToExpressionNode() works just fine. This sounds like some sort of bug? Is there a workaround?

   at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)
   at Serialize.Linq.Factories.TypeResolverNodeFactory.TryToInlineExpression(MemberExpression memberExpression, Expression& inlineExpression)
   at Serialize.Linq.Factories.TypeResolverNodeFactory.ResolveMemberExpression(MemberExpression memberExpression)
   at Serialize.Linq.Factories.TypeResolverNodeFactory.Create(Expression expression)
   at Serialize.Linq.Nodes.BinaryExpressionNode.Initialize(BinaryExpression expression)
   at Serialize.Linq.Nodes.ExpressionNode`1..ctor(INodeFactory factory, TExpression expression)
   at Serialize.Linq.Nodes.BinaryExpressionNode..ctor(INodeFactory factory, BinaryExpression expression)
   at Serialize.Linq.Factories.NodeFactory.Create(Expression expression)
   at Serialize.Linq.Factories.TypeResolverNodeFactory.Create(Expression expression)
   at Serialize.Linq.Nodes.BinaryExpressionNode.Initialize(BinaryExpression expression)
   at Serialize.Linq.Nodes.ExpressionNode`1..ctor(INodeFactory factory, TExpression expression)
   at Serialize.Linq.Nodes.BinaryExpressionNode..ctor(INodeFactory factory, BinaryExpression expression)
   at Serialize.Linq.Factories.NodeFactory.Create(Expression expression)
   at Serialize.Linq.Factories.TypeResolverNodeFactory.Create(Expression expression)
   at Serialize.Linq.Nodes.BinaryExpressionNode.Initialize(BinaryExpression expression)
   at Serialize.Linq.Nodes.ExpressionNode`1..ctor(INodeFactory factory, TExpression expression)
   at Serialize.Linq.Nodes.BinaryExpressionNode..ctor(INodeFactory factory, BinaryExpression expression)
   at Serialize.Linq.Factories.NodeFactory.Create(Expression expression)
   at Serialize.Linq.Factories.TypeResolverNodeFactory.Create(Expression expression)
   at Serialize.Linq.Nodes.LambdaExpressionNode.Initialize(LambdaExpression expression)
   at Serialize.Linq.Nodes.ExpressionNode`1..ctor(INodeFactory factory, TExpression expression)
   at Serialize.Linq.Nodes.LambdaExpressionNode..ctor(INodeFactory factory, LambdaExpression expression)
   at Serialize.Linq.Factories.NodeFactory.Create(Expression expression)
   at Serialize.Linq.Factories.TypeResolverNodeFactory.Create(Expression expression)
   at Serialize.Linq.Factories.DefaultNodeFactory.Create(Expression expression)
   at Serialize.Linq.Serializers.ExpressionConverter.Convert(Expression expression)
   at Serialize.Linq.Extensions.ExpressionExtensions.ToExpressionNode(Expression expression)

Nullable<Decimal> deserialization issue

Hi!
I found one little bug with JSON deserialization of Nullable type.
When created without a floating point, e.g. 0m, Decimal is serialized without it too. Then deserializer thinks it is Int32 and fails to find corresponding constructor on Nullable.

An example of code that fails:

var c = Expression.Constant(0m, typeof (Decimal?));
var json = c.ToJson();
var expr = new JsonSerializer().Deserialize<ExpressionNode>(json).ToExpression();

There is an easy workaround for now, thanks to ValueConverter:

Serialize.Linq.Internals.ValueConverter.AddCustomConverter(typeof(Nullable<Decimal>), p =>
{
    var d = Convert.ToDecimal(p);
    return (Decimal?)d;
});

WCF client proxy compile error

Thanks for the great work!

There is a problem when I try to use the library on a WCF client.
I have added a reference to the library in both the WCF server and client, but still, I get 14 compile errors on the generated WCF client proxy class in Reference.cs, all similar to this: ...ExpressionNodeOfNewExpressionQsd8_SODT does not implement inherited abstract member 'Serialize.Linq.Nodes.ExpressionNode.ToExpression(Serialize.Linq.ExpressionContext)'

If I comment out all these auto-generated classes with errors from Reference.cs file, it works well.

I am using C# 4.5 and the latest library version from nuget - 1.1.4 from 5/10/2013.

Issue serializing collections inside expressions

I grabbed the latest snapshot of the code (after seeing the addition of collection serialization)... could be that I misunderstood the usage model, but in any case:

I have a WCF service operation that looks like this:

public IEnumerable<int> GetNumbers(ExpressionNode node)
{
     List<int> numbers = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 
     return Filter(node, numbers);
}

public static IEnumerable<T> Filter<T>(ExpressionNode node, IEnumerable<T> source)
{
    var exp = node.ToBooleanExpression<T>().Compile();
    return source.Where(x => exp(x)).ToArray();
}

I am trying to send the following expression to the service:

var nums = new List<int> { 1, 2, 3 };
Expression<Func<int, bool>> e3 = (i => nums.Any(n => n == i));
var numsresult = client.GetNumbers(e3.ToExpressionNode());

and get a nasty exception (detailed below). it looks like the Expression node is created OK with the array values are there..

System.ServiceModel.CommunicationException was unhandled
HResult=-2146233087
Message=There was an error while trying to serialize parameter http://tempuri.org/:node. The InnerException message was 'Type 'System.Collections.Generic.List1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]' with data contract name 'ArrayOfint:http://schemas.microsoft.com/2003/10/Serialization/Arrays' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details. Source=mscorlib StackTrace: Server stack trace: at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameterPart(XmlDictionaryWriter writer, PartInfo part, Object graph) at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameter(XmlDictionaryWriter writer, PartInfo part, Object graph) at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameters(XmlDictionaryWriter writer, PartInfo[] parts, Object[] parameters) at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeBody(XmlDictionaryWriter writer, MessageVersion version, String action, MessageDescription messageDescription, Object returnValue, Object[] parameters, Boolean isRequest) at System.ServiceModel.Dispatcher.OperationFormatter.SerializeBodyContents(XmlDictionaryWriter writer, MessageVersion version, Object[] parameters, Object returnValue, Boolean isRequest) at System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessage.OperationFormatterBodyWriter.OnWriteBodyContents(XmlDictionaryWriter writer) at System.ServiceModel.Channels.BodyWriterMessage.OnWriteBodyContents(XmlDictionaryWriter writer) at System.ServiceModel.Channels.Message.OnWriteMessage(XmlDictionaryWriter writer) at System.ServiceModel.Channels.BufferedMessageWriter.WriteMessage(Message message, BufferManager bufferManager, Int32 initialOffset, Int32 maxSizeQuota) at System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset) at System.ServiceModel.Channels.HttpOutput.SerializeBufferedMessage(Message message, Boolean shouldRecycleBuffer) at System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout) at System.ServiceModel.Channels.HttpChannelFactory1.HttpRequestChannel.HttpChannelRequest.SendRequest(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at WcfService1Client.ServiceReference1.IService1.GetNumbers(ExpressionNode node)
at WcfService1Client.ServiceReference1.Service1Client.GetNumbers(ExpressionNode node) in c:\Users\xxxx\Documents\Visual Studio 2013\Projects\Sandbox2014\WcfService1Client\Service References\ServiceReference1\Reference.cs:line 251
at WcfService1Client.Program.Main(String[] args) in c:\Users\xxxx\Documents\Visual Studio 2013\Projects\Sandbox2014\WcfService1Client\Program.cs:line 32
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException: System.Runtime.Serialization.SerializationException
HResult=-2146233076
Message=Type 'System.Collections.Generic.List`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]' with data contract name 'ArrayOfint:http://schemas.microsoft.com/2003/10/Serialization/Arrays' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
Source=System.Runtime.Serialization
StackTrace:
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeAndVerifyType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, Boolean verifyKnownType, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiType(XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
at WriteConstantExpressionNodeToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , ClassDataContract )
at System.Runtime.Serialization.ClassDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeAndVerifyType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, Boolean verifyKnownType, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiType(XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
at WriteExpressionNodeListToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , CollectionDataContract )
at System.Runtime.Serialization.CollectionDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
at WriteMethodCallExpressionNodeToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , ClassDataContract )
at System.Runtime.Serialization.ClassDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeAndVerifyType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, Boolean verifyKnownType, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiType(XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
at WriteLambdaExpressionNodeToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , ClassDataContract )
at System.Runtime.Serialization.ClassDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeAndVerifyType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, Boolean verifyKnownType, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiTypeAtTopLevel(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle originalDeclaredTypeHandle, Type graphType)
at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.WriteObject(XmlDictionaryWriter writer, Object graph)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameterPart(XmlDictionaryWriter writer, PartInfo part, Object graph)
InnerException:

TypeBinaryExpression serialization/deserialization bug

TypeBinaryExpressionNode is serialized incorrectly: TypeOperand field is missing. Deserialization is also performed incorrectly: TypeBinaryExpression instance is constructed using wrong type as a second parameter (expression result type is used instead of TypeOperand).

There is a test method for this case (SimpleTypeBinaryTest) which doesn't work well. It is always passed regardless of the bug. This leads to another issue with the AssertExpression helper method. See issue #14

I'm going to provide fix for this issue in an upcoming pull request.

Licence

Would it be possible to change the Licence to LGPL, so the Library can also be used in closed source Applications?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.