广西住房和城乡建设网站,uc自媒体平台注册,东莞网站优化公司哪家好,想找人做网站 要怎么选择一#xff1a;背景 1. 讲故事前几天看同事在用 linq 给内存中的两个 model 做左连接#xff0c;用过的朋友都知道#xff0c;你一定少不了一个叫做 DefaultIfEmpty 函数#xff0c;这玩意吧#xff0c;本来很流畅的 from...in...join, 突然搞进来这么一个函数#xff0c;… 一背景 1. 讲故事前几天看同事在用 linq 给内存中的两个 model 做左连接用过的朋友都知道你一定少不了一个叫做 DefaultIfEmpty 函数这玩意吧本来很流畅的 from...in...join, 突然搞进来这么一个函数真的是恶心他妈给恶心开门恶心到家了简化后的代码如下class User{public int UserID { get; set; }public string Email { get; set; }}class Order{public int OrderID { get; set; }public string OrderTitle { get; set; }public int UserID { get; set; }}static void Main(string[] args){var userList new ListUser(){new User(){ UserID1, Email333qq.com},new User(){ UserID2, Email444qq.com},};var orderList new ListOrder(){new Order(){ OrderID1, OrderTitle订单1, UserID1},new Order(){ OrderID2, OrderTitle订单2, UserID1}};var query from u in userListjoin o in orderList on u.UserID equals o.UserID into grpfrom item in grp.DefaultIfEmpty()select new { UserID u.UserID, OrderTitle item?.OrderTitle }; } 之所以出现这个情况是因为不管是 查询关键词 还是 扩展方法都并没有直接对 leftjoin 和 rightjoin 底层支持只能通过变通的方式去实现这就很尴尬了比如说上面的这段代码你很难在多天之后还能准确理解这里的 DefaultIfEmpty 是用来干嘛的那现在问题的关键在于有没有什么方法让底层支持或者有可信的第三方帮我封装好还真巧在 github 上 还真有一个 morelinq 项目https://github.com/morelinq/MoreLINQ看 md 是给 Enumerable 扩展了 6070 个方法如虎添翼呀接下来一起来探索下吧。二MoreLinq 下的探索 1. 安装安装非常简单用 nuget 跑一下 Install-Package morelinq -Version 3.3.2 即可。2. LeftJoin / RightJoin / FullJoin在 morelinq 中就提供了 左外右边全连接这就很????????了提高开发效率让我们更加专注业务这里就使用 leftjoin 来改造刚才的代码,代码如下var query2 userList.LeftJoin(orderList, u u.UserID, o o.UserID,u new { UserID u.UserID, OrderTitle default(string) },(u, o) new { UserID u.UserID, OrderTitle o.OrderTitle });怎么样一句链式就搞定了而且代码还非常好理解。第一个参数join 集合第二个参数source 集合的关联 id第三个参数join 集合的关联 id第四个参数source 存在join不存在 应该返回的 model 架构第五个参数source,join 都存在 应该返回的 model 架构刚才也说到了有6070个扩展方法大家可以去趴一趴其他有趣的东西这里我推荐几个给大家演示一下毕竟还是非常实用的。3. Shuffle从字面意思上看就是洗牌挺实用的一个方法很多时候我希望在一个集合中随机抽取一条记录比如说我有10套邮件模板当用户下订单之后我希望可以随机抽一套模板给用户以防被 qq邮箱 放入垃圾箱中原来我需要是用 new guid 来实现,如下代码var list new Listint() { 1, 3, 5, 7, 9, 11, 12 };var query list.OrderBy(m Guid.NewGuid());Console.WriteLine(string.Join(,,query));---- output -----11,7,9,12,5,3,1现在就简单多了直接使用 Shuffle 搞定。var list new Listint() { 1, 3, 5, 7, 9, 11, 12 };var query list.Shuffle();Console.WriteLine(string.Join(,, query));----- output ------5,1,9,12,7,3,114. Insert有时候我需要在 IEnumerable 集合的指定位置插入一个集合举个例子 A { 1, 3, 5, 7, 9, 11, 12 }, B {8}, 我希望将 8 插入到 7 和 9 之间在现有的 Enumerable 下只有 Concat 和 Append 方法无法做到指定插入这个需求又可以被 moreqlinq 搞定啦。。。代码如下IEnumerableint list new Listint() { 1, 3, 5, 7, 9, 11, 12 };var query list.Insert(new Listint() { 8 }, 4);Console.WriteLine(string.Join(,, query));可以看到往一个集合的指定位置插入一个集合就是这么轻松如意太爽啦~~~5. ForEach不知道什么原因至今在 IEnumerable 下都没有提供 ForEach 扩展方法我这个升斗小民反正是体会不到这么设计的哲学在哪里在原来你只能 ToList 立即执行要么使用 foreach 进行延期遍历现在就方便多了简化的代码如下IEnumerableint list new Listint() { 1, 3, 5, 7, 9, 11, 12 };list.ForEach(m {Console.Write(m );});6. ToDataTable对在看的各位大佬估计都用不上对我们公司几个 10 年的项目那是万万不能少哈如有能用得上的可以简单看一下非常简单不过我还是好奇一下它是怎么做到的可以用 ilspy 去翻翻它的源码
public static TTable ToDataTableT, TTable(this IEnumerableT source, TTable table, params ExpressionFuncT, object[] expressions) where TTable : DataTable
{MemberInfo[] members PrepareMemberInfos(expressions).ToArray();members BuildOrBindSchema(table, members);FuncT, object[] func CreateShredderT(members);table.BeginLoadData();try{foreach (T item in source){DataRow dataRow table.NewRow();dataRow.ItemArray func(item);table.Rows.Add(dataRow);}return table;}finally{table.EndLoadData();}
}private static IEnumerableMemberInfo PrepareMemberInfosT(ICollectionExpressionFuncT, object expressions)
{if (expressions null || expressions.Count 0){return typeof(T).GetMembers(BindingFlags.Instance | BindingFlags.Public).Where(delegate(MemberInfo m){if (m.MemberType ! MemberTypes.Field){PropertyInfo propertyInfo m as PropertyInfo;if ((object)propertyInfo ! null propertyInfo.CanRead){return propertyInfo.GetIndexParameters().Length 0;}return false;}return true;});}try{return expressions.Select(GetAccessedMember);}catch (ArgumentException innerException){throw new ArgumentException(One of the supplied expressions is not allowed., expressions, innerException);}MemberInfo GetAccessedMember(LambdaExpression lambda){Expression expression lambda.Body;if (expression.NodeType ExpressionType.Convert || expression.NodeType ExpressionType.ConvertChecked){expression ((UnaryExpression)expression).Operand;}MemberExpression memberExpression expression as MemberExpression;if (memberExpression null || memberExpression.Expression.NodeType ! ExpressionType.Parameter){throw new ArgumentException($Illegal expression: {lambda}, lambda);}return memberExpression.Member;}
}从上面源码大概可以看到将 List 转成 DataTable 支持两种方式要么反射要么 Expression 解析树默认用的是反射性能要稍微低一点。三总结 当然这里还有很多的扩展方法篇幅原因恕不能一一介绍有兴趣的朋友可以pull下来试一试总的来说这种工具类太棒了让我们可以更好的专注于业务。