创建一个c# LINQ可选的Join扩展
本文关键字:Join 扩展 LINQ 一个 创建 | 更新日期: 2023-09-27 18:12:44
我正试图为Linq扩展,我可以使用可选的连接。我想我快找到了,但我还是少了点什么。你能发现吗?
public static IQueryable<T> OptionalJoin<T>(this IQueryable<T> source, bool condition,
Expression<IEnumerable<T>> TInner,
Expression<Func<T, object>> outerKeySelector,
Expression<Func<T, object>> innerKeySelector,
Expression<Func<IQueryable<T>, IEnumerable<T>, object>> resultSelector)
{
return condition ? source.Join(TInner, outerKeySelector, innerKeySelector, resultSelector) : source;
}
可选连接实际上没有多大意义。您的返回类型是IQueryable<T>
,如果您想返回原始集合,这是正确的。但如果你想加入一些东西,返回类型就必须改变。你也不能让一个方法根据运行时条件返回不同的编译时类型。
正因为如此,我认为你想做的事是不可能的。
我能想象这样的事情可以工作的唯一方法是,如果你有两个结果选择器:一个是当condition
为真,另一个是当它为假。它们都将返回相同的类型。
还有,你的代码中有几个错误,我试图修复。
public static IQueryable<TResult> OptionalJoin<TSource, TInner, TKey, TResult>(
this IQueryable<TSource> source,
bool condition,
IQueryable<TInner> innerCollection,
Expression<Func<T, TKey>> outerKeySelector,
Expression<Func<T, TKey>> innerKeySelector,
Expression<Func<TSource, TInner, TResult>> trueResultSelector,
Expression<Func<TSource, TResult>> falseResultSelector)
{
return condition
? source.Join(innerCollection, outerKeySelector, innerKeySelector, trueResultSelector)
: source.Select(falseResultSelector);
}
我想你会需要这样的东西:
public static IQueryable<TResult> OptionalJoin<TOuter, TInner, TKey, TResult>(
this IQueryable<TOuter> outer,
bool condition,
IEnumerable<TInner> inner,
Expression<Func<TOuter, TKey>> outerKeySelector,
Expression<Func<TInner, TKey>> innerKeySelector,
Expression<Func<TOuter, TInner, TResult>> joinResultSelector,
Expression<Func<TOuter, TResult>> outerResultSelector)
{
return condition
? outer.Join(inner,
outerKeySelector,
innerKeySelector,
joinResultSelector)
: outer.Select(outerResultSelector);
}
构建这样的操作符时,需要从内置操作符的签名开始,并尽可能保留参数签名。您正在有效地合并Join
和Select
,因此从它们开始:
IQueryable<TResult> Join<TOuter, TInner, TKey, TResult>(
this IQueryable<TOuter> outer,
IEnumerable<TInner> inner,
Expression<Func<TOuter, TKey>> outerKeySelector,
Expression<Func<TInner, TKey>> innerKeySelector,
Expression<Func<TOuter, TInner, TResult>> resultSelector)
public static IQueryable<TResult> Select<TSource, TResult>(
this IQueryable<TSource> source,
Expression<Func<TSource, TResult>> selector)
你的代码有一些签名错误。
另外,你可以很容易地减少我的答案,只使用T
:
public static IQueryable<T> OptionalJoin<T, K>(
this IQueryable<T> outer,
bool condition,
IEnumerable<T> inner,
Expression<Func<T, K>> outerKeySelector,
Expression<Func<T, K>> innerKeySelector,
Expression<Func<T, T, T>> joinResultSelector)
{
return condition
? outer.Join(inner,
outerKeySelector,
innerKeySelector,
joinResultSelector)
: outer;
}