排名
55
文章
5
粉丝
8
评论
4
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:
50010702506256


欢迎加群交流技术
原
.NET实现ORM-EF的Lambda查询一对多转一对一,即实现List<T>.SelectMany()方法,并对其进行为空处理

我们借助微软官方方法参数进行修改实现命名方法为MySelectMAny:
public static IEnumerable<TResult> MySelectMAny<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector);
泛型参数理解:
TSource:数据源泛型
TCollection:解析字段后的泛型
TResult:返回值泛型
实现步骤(利用嵌套foreach()和传入委托进行循环遍历):
1.预先创建一个返回值对象集合
List<TResult> listTResult = new List<TResult>();
2.利用foreach()循环遍历数据源
foreach (TSource itemMany in source){}
3.利用foreach()和collectionSelector()委托嵌于上一个循环中,循环遍历需要解析的字段(即本文itemMany)
foreach (TCollection itemone in collectionSelector(itemMany)){}
4.通过判断解析后获得的值,进行返回值对象的创建、赋值和是否需要添加至返回值对象集合中
if(itemtwo!=null){
//创建一个返回对象
TResult tResult=default(TResult);
//利用resultSelector()委托,将返回值赋给返回对象
tResult = resultSelector(itemMany, itemone);
//将返回值对象添加到返回值对象集合中
listTResult.Add(tResult);
}
5.最后返回对象集合
具体代码:
//拓展方法创建
public static class SelectManyExtands
{
public static IEnumerable<TResult> MySelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource,TCollection, TResult> resultSelector)
{
//创建一个返回值对象集合
List<TResult> listTResult = new List<TResult>();
//利用foreach()循环遍历数据源
foreach (TSource itemMany in source)
{
//利用foreach()和collectionSelector()委托,循环遍历需要解析的字段
foreach (TCollection itemone in collectionSelector(itemMany))
{
//进行判断
if(itemone!=null){
//创建一个返回对象
TResult tResult=default(TResult);
//利用resultSelector()委托,将返回值赋给返回对象
tResult = resultSelector(itemMany, itemone);
//将返回值对象添加到返回值对象集合中
listTResult.Add(tResult);
}
}
}
return listTResult;
}
}
微软官方并未对该方法进行为空处理,若用户在使用官方的List.SelectMany()方法时在第一个委托解析数据时使用DefaultIfEmpty()运行时会报错,我们个人实现该方法可实现为空不报错功能,如下:
.如果解析后值为空,我们可以预先实例化一个对象,将对象空值赋于返回值对象,但是使用TCollection tCollection = new TCollection();
,其会报变量类型没有new()约束的错误,若我们在拓展方法后加上whewe TCollection:new()
则代码就多了限制,代码耦合度就高了,所以我们使用反射(利用类型创建对象),即:类型 类型名=Activator.CreateInstance<类型名>();
,就解决了。
为空处理后完整代码:
//拓展方法创建
public static class SelectManyExtands
{
public static IEnumerable<TResult> MySelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource,TCollection, TResult> resultSelector)
{
//创建一个返回值对象集合
List<TResult> listTResult = new List<TResult>();
//利用foreach()循环遍历数据源
foreach (TSource itemMany in source)
{
//利用foreach()和collectionSelector()委托,循环遍历需要解析的字段
foreach (TCollection itemone in collectionSelector(itemMany))
{
//创建一个返回对象
TResult tResult=default(TResult);
//判断itemtwo是否为空,如果为空则预先利用反射(使用类型创建对象)创建一个对象,代替为空的itemone传入resultSelector()委托中去
if(itemone==null){
//利用反射,使用类型创建对象
TCollection tcollection=Activator.CreateInstance<TCollection>();
//利用resultSelector()委托,反射传创建的对象tcollection代替itemone传入委托,将返回值赋给返回对象
tResult = resultSelector(itemMany,tcollection);
}else{
//利用resultSelector()委托,将返回值赋给返回对象
tResult = resultSelector(itemMany, itemone);
}
//将返回值对象添加到返回值对象集合中
listTResult.Add(tResult);
}
}
return listTResult;
}
}
评价
剑轩
nice
,分析得很不错!