日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Advanced Linq - Dynamic Linq query library: Add support for 'Contains' extension

發布時間:2025/3/19 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Advanced Linq - Dynamic Linq query library: Add support for 'Contains' extension 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文鏈接: http://blog.walteralmeida.com/2010/05/advanced-linq-dynamic-linq-library-add-support-for-contains-extension-.html

?

This post explains how to extend the Dynamic Linq library to support the "Contains" extension method.?This post also can serve as a base for further extension of the Dynamic Linq Library and adding support to more extension methods.

Linq is an amazing programming model, brought to life by the Microsoft.NET Framework 3.5, that introduces data queries as a first-class concept into any Microsoft programming langage.

Linq allows you to build strongly type queries to access data in any source for which a Linq support library is available, including MS SQL, data objects (through IEnumerable and IQueryable), Entity Framework and more.

Even though the regular, strongly typed approach to building queries is definitively recommended, in some cases arises the need for dynamically building queries. For this purpose Microsoft freely provides an open source dynamic Linq query library. Cases for using dynamic queries could be for example: you might want to provide business intelligence UI within your application that allows an end-user business analyst to use drop-downs to build and express their own custom queries/views on top of data. Another example is the creation of RESTfull service interfaces that accept query string parameters that could be converted to dynamic linq queries.

Please refer the the Scott Guthrie post for more information on the Dynamic Linq Query library:

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx?

I found this library very usefull and used it in several scenarios. However this library does not support all of the Linq extensions. I had the need for building dynamic queries with the "Contains" extension which was not supported by the Microsoft Dynamic Linq library.?This post explains how to extend the Dynamic Linq library to support the "Contains" extension method.?

Sample Code

Here is the sample application we use to illustrate our tallks (You can download the source code?here) :?

We define a class "Contact". For the purpose of demonstration, we do not connect to a data source, but have a static "GetContactList" method that return a collection of users.?

1 public class Contact 2 { 3 public string FirstName { get; set; } 4 public string LastName { get; set; } 5 public DateTime BirthDate { get; set; } 6 public string Country { get; set; } 7 8 public Contact(string firstName, string lastName, DateTime birthDate, string country) 9 { 10   FirstName = firstName; 11   LastName = lastName; 12   BirthDate = birthDate; 13   Country = country; 14 } 15 16 public override string ToString() 17 { 18 return string.Concat(FirstName, " ", LastName, " ", BirthDate, " ",Country); 19 } 20 21 public static List?contact? GetContactsList() 22 { 23 var result = new List?contact?(); 24 25 result.Add(new Contact("Zephr", "Austin", new DateTime(1967, 11, 07), "Afghan")); 26 result.Add(new Contact("Odette", "Bean", new DateTime(1993, 05, 18), "Uzbekistan")); 27 result.Add(new Contact("Maggie", "Mcson", new DateTime(2001, 06, 12),"Kiribati")); 28 ... 29 ... 30 31 return result; 32 } 33 }

??

The Case?– Use of the Dynamic Linq Library and missing support for the “Contains”? extension method

Let's take a first example of simple Linq query to get the contacts located in Austria. Using regular Linq, you write the following query:

var query = from c in Contact.GetContactsList() where c.Country == "Austria" select c;

Or the equivalent query, using extension methods and lambda?

var query = Contact.GetContactsList().Where(c => c.Country == "Austria");

We will keep the second syntax as the dynamic linq library does not support the first syntax.

We can then iterate the query result and retrieve relevant contact information:

foreach (var contact in query) {Console.WriteLine(contact.ToString()); }

?Doing the same query using dynamic Linq:?

query = Contact.GetContactsList().AsQueryable().Where("Country == @0", "Austria");

Please not the extra "AsQueryable()" call because the dynamic extension applies on collections implementing IQueryable. Then Iterating the results is just the same as with regular Linq.

The Dynamic Linq library also supports more complex queries. For instance here is the Dynamic Linq query to retrieve all contacts in Austria, born in 1957:?

query = Contact.GetContactsList().AsQueryable().Where("Country == @0 && BirthDate.Year == 1957", "Austria");

?

Everythings seems to magically work so far. Let’s try now a more complex scenario: when want to retrieve the list of contacts located in given list of countries. Let’s say : all contacts located in either Austria or Poland. For such a purpose, a common solution is to use the “Contains” extension method:

query = Contact.GetContactsList().Where(c => new List<string>>() { "Austria","Poland" }.Contains(c.Country));

?

In Linq to SQL, the result pseudo SQL projection would be:

select * from contact c where c.Country in (‘Austria’, ‘Poland’);

?

Let’s try to write the same query in Dynamic Linq (using parameters to pass the input list of countries):

query = Contact.GetContactsList().AsQueryable().Where("@0.Contains(Country)", newList<string>() { "Austria", "Poland" });

?

This result at runtime to the following exception:?“No applicable aggregate method 'Contains' exists”,

Emphasizing the fact the Dynamic Linq library does not have support for the “Contains” extension method. The following section will explains how to add support for “Contains”.

?

Add support for the “Contains” extension method

Analyzing the “Dynamic.cs” class that adds support for Dynamic Linq, you’ll find the definition of the?IEnumerableSignatures?interface. This interface lists all?IEnumerable?extension methods that are supported by the Dynamic Linq library. You should add the “Contains” extension method signature:

interface IEnumerableSignatures {void Contains(object selector);void Where(bool predicate);void Any();void Any(bool predicate);void All(bool predicate);void Count();void Count(bool predicate);void Min(object selector);void Max(object selector);void Sum(int selector);void Sum(int? selector);void Sum(long selector);void Sum(long? selector);void Sum(float selector);void Sum(float? selector);void Sum(double selector);void Sum(double? selector);void Sum(decimal selector);void Sum(decimal? selector);void Average(int selector);void Average(int? selector);void Average(long selector);void Average(long? selector);void Average(float selector);void Average(float? selector);void Average(double selector);void Average(double? selector);void Average(decimal selector);void Average(decimal? selector); }

?

The?IEnumerableSignatures?interface is then used in the following method:

?

Expression ParseAggregate(Expression instance, Type elementType, string methodName, int errorPos) {ParameterExpression outerIt = it;ParameterExpression innerIt = Expression.Parameter(elementType, "");it = innerIt;Expression[] args = ParseArgumentList();it = outerIt;MethodBase signature;if (FindMethod(typeof(IEnumerableSignatures), methodName, false, args, out signature) != 1)throw ParseError(errorPos, Res.NoApplicableAggregate, methodName);Type[] typeArgs;if (signature.Name == "Min" || signature.Name == "Max") {typeArgs = new Type[] { elementType, args[0].Type };}else {typeArgs = new Type[] { elementType };}if (args.Length == 0) {args = new Expression[] { instance };}else {args = new Expression[] { instance, Expression.Lambda(args[0], innerIt) };}return Expression.Call(typeof(Enumerable), signature.Name, typeArgs, args); }

?

There 2 changes to perform to that method.

Fist, the arguments are constructed using the following line:

args = new Expression[] { instance, Expression.Lambda(args[0], innerIt) };

?

this has to be changed specifically for the Contains methods to the following:

args = new Expression[] { instance, args[0] };

Reason is that the signature of the Contains extension methods differs from the others. Let’s take an example: here are the definitions for the “Any” and “Contains” extension methods of the IEnumerable<> interface (classe “System.Linq.Enumerable”):

Any<TSource>(this.System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,bool>); Contains<TSource>(this.System.Collections.Generic.IEnumerable<TSource>, TSource);

You can see that the parameter of the “Any” extension method is a lambda expression taking “TSource” (type of innerIt in our Dynamic Linq library) as entry and returning ”bool” .This explains the transformation Expression.Lambda(args[0], innerIt). In the case of the “Contains” extension method, type of the argument is not a Lambda but just “TSource”.

Next change is the following: the Dynamic Linq library transforms the input string to a proper Linq query by parsing the input string. It internally keeps a context to the current collection being processed. This is the use of the field “innerIt”. When processing our list of “Contacts”, the innerIt represent a “Contact”. However, when processing the “Contains” method, the context changes from the list of “Contacts” to the list being the source for the “Contains” method; in our case: the list of string representing country name. Therefore the parsing of the following dynamic Linq expression:

query = Contact.GetContactsList().AsQueryable().Where("@0.Contains(Country)", newList<String>() { "Austria", "Poland" });

will not work: the parser will try to find a property “Country” on type String, where we meant a property “Country” on “Contact”.

In fact the previous query is equivalent to:

query = Contact.GetContactsList().AsQueryable().Where("@0.Contains(it.Country)", newList<String>() { "Austria", "Poland" });

Where “it” is the keyword defined in the Dynamic Linq library to represent the current element. It represents here the current item in the list {“Austria”, “Poland”}. What we would like here is the following syntax:

query = Contact.GetContactsList().AsQueryable().Where("@0.Contains(outerIt.Country)", newList<String>() { "Austria", "Poland" });

where “outerIt” represents the englobing context: the list of “Contacts”.? For this we should define an “outerIt” keyword, and use it in the “ParseAggregate” method. The new implementation of the “ParseAggregate” methods is now:

Expression ParseAggregate(Expression instance, Type elementType, string methodName, int errorPos) {outerIt = it;ParameterExpression innerIt = Expression.Parameter(elementType, "");it = innerIt;Expression[] args = ParseArgumentList();it = outerIt;MethodBase signature;if (FindMethod(typeof(IEnumerableSignatures), methodName, false, args, out signature) != 1)throw ParseError(errorPos, Res.NoApplicableAggregate, methodName);Type[] typeArgs;if (signature.Name == "Min" || signature.Name == "Max") {typeArgs = new Type[] { elementType, args[0].Type };}else{typeArgs = new Type[] { elementType };}if (args.Length == 0) {args = new Expression[] { instance };}else {if (signature.Name == "Contains")args = new Expression[] { instance, args[0] };elseargs = new Expression[] { instance, Expression.Lambda(args[0], innerIt) };}return Expression.Call(typeof(Enumerable), signature.Name, typeArgs, args); }

?

By the way: it is important to mention that since “it” and “outerIt” are defined keywords, they become reserved keywords and should not be used as properties or method definitions in your data classes, if you intend to access them as part of dynamic queries. It would result in a runtime error. Since the common used code standards are to use only capitalized names for public properties and methods, it should be alright in most of the cases.

Remains the use of the “outerIt” keyword. Definition of the keyword and class level storage of its current value:

static readonly string keywordOuterIt = "outerIt"; ParameterExpression outerIt;

?

Taking into account the new keyword in ??ParseIdentifier??

Expression ParseIdentifier() {ValidateToken(TokenId.Identifier);object value;if (keywords.TryGetValue(token.text, out value)) {if (value is Type) return ParseTypeAccess((Type)value);if (value == (object)keywordIt) return ParseIt();if (value == (object)keywordOuterIt) return ParseOuterIt();if (value == (object)keywordIif) return ParseIif();if (value == (object)keywordNew) return ParseNew();NextToken();return (Expression)value;}......

?

And new method “ParseOuterIt”:

?

Expression ParseOuterIt() {if (outerIt == null)throw ParseError(Res.NoItInScope);NextToken();return outerIt; }

?

Conclusion

?

That’s it?! The Dynamic Linq library is now supporting the ??Contains?? extension method

You’ll find the modified “Dynamic.cs” class as part of the code sample. You can now write and successfully run queries likes the following:

query = Contact.GetContactsList().AsQueryable().Where("@0.Contains(outerIt.Country)", newList<String>() { "Austria", "Poland" });

or:

query = Contact.GetContactsList().AsQueryable().Where("@0.Contains(outerIt.Country) && it.BirthDate.Year > @1", new List<string>() { "Austria", "Poland" }, 1955);

This post can be used to further extend the Dynamic Linq library and add support for more extension methods.

Hope this can help other who faced the same limitation and help move forward the Dynamic Linq Library!

You can download the source code for the sample project?here. or here

轉載于:https://www.cnblogs.com/oxsir/p/advanced-linq-dynamic-linq-library-add-support-for-contains-extension.html

總結

以上是生活随笔為你收集整理的Advanced Linq - Dynamic Linq query library: Add support for 'Contains' extension的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲性图一区二区三区 | 91视频88av| 国产精品久久久久久久av福利 | 无码人妻丰满熟妇区96 | 大学生高潮无套内谢视频 | 秋霞二区| 久久2018| 老司机成人免费视频 | 午夜色大片 | 免费公开在线视频 | 欧美成人高潮一二区在线看 | 中文精品久久久久人妻不卡 | 日韩一级片在线 | 精品一区二区人妻 | 亚洲精品人人 | 国产日韩亚洲 | 亚洲精品乱码久久久久久蜜桃图片 | 国产乱子伦视频一区二区三区 | 日本久久免费 | www日| 国产熟妇一区二区三区四区 | 天天干天天综合 | 波多野结衣爱爱 | 高潮毛片无遮挡免费看 | 国产一级片免费视频 | www.操.com| 超碰cc | 欧美视频亚洲视频 | 欧美成人69 | 很嫩很紧直喷白浆h | 国产白丝袜美女久久久久 | 国产精品国产三级国产aⅴ下载 | 女人张开双腿让男人捅 | 国内成人精品 | 色婷婷狠狠18禁久久 | 老司机午夜av | 99综合久久 | 人妻无码一区二区三区四区 | 熟女俱乐部一区二区 | 久久精品欧美一区二区三区不卡 | 免费视频中文字幕 | 美女上床网站 | 中日韩男男gay无套 人人草人人干 | 一二三区不卡 | 日韩午夜精品视频 | 2023毛片 | 亚洲综合站 | 精品三级av | 最新av电影网站 | 天天干精品 | 日韩欧美视频免费在线观看 | 好紧好爽再浪一点视频 | 四虎新网站 | 中国亚洲女人69内射少妇 | 亚洲国产精品久久久久久6q | 琪琪色视频 | 国产中文久久 | 久久极品 | 岳狂躁岳丰满少妇大叫 | 99久久一区 | 在线免费黄色网址 | 交专区videossex农村 | 少妇精品视频一区二区 | 在线播放精品视频 | 亚洲免费大片 | 久久男人精品 | 亚洲色图丝袜美腿 | 午夜爽爽爽 | 高潮videossex高潮 | 欧美日韩一区二区三区四区五区 | 美女张开腿让男人桶爽 | 一区二区三区在线视频免费观看 | 中文字幕中出 | av一区免费 | 超碰伦理| 五月天久久 | 成年人免费网站 | 免费久久一级欧美特大黄 | 胖女人做爰全过程 | 欧美精品久久久久久久 | 日韩一区二区不卡 | 国产精品500部 | 特黄做受又粗又大又硬老头 | 一卡二卡三卡四卡 | 亚洲一区二区观看播放 | 久久久久久av | 欧美黄在线观看 | av在线成人 | 视频免费观看在线 | 日本久久影视 | 高清一区在线观看 | 爱综合网| 日美韩一区二区三区 | 婷婷色图 | 欧美你懂的| 一起草在线视频 | 日本乱偷人妻中文字幕在线 | 精品人妻av在线 | 波多野结衣精品视频 |