假设您的目标是 LINQ to Objects。
实际上Join 方法需要3 个表达式(函数)- 外键选择器、内键选择器和结果选择器。由于您要连接两个相同类型的可枚举,因此外部和内部键选择器将是相同的。
如果属性的数量不超过7,我们可以使用Tuple<>作为key。以下是我们如何动态构建选择器:
static Func<T, object> CreateSelector<T>(IEnumerable<string> propertyNames)
{
var sourceType = typeof(T);
var parameter = Expression.Parameter(sourceType, "e");
var properties = propertyNames.Select(name => Expression.PropertyOrField(parameter, name)).ToArray();
var selector = Expression.Lambda<Func<T, object>>(
Expression.Call(typeof(Tuple), "Create", properties.Select(p => p.Type).ToArray(), properties),
parameter);
return selector.Compile();
}
然后我们可以创建一个使用它的辅助方法(将这两个方法放在您选择的某个顶级公共静态类中):
public static IEnumerable<Tuple<T, T>> Join<T>(this IEnumerable<T> left, IEnumerable<T> right, IEnumerable<string> propertyNames)
{
var keySelector = CreateSelector<T>(propertyNames);
return left.Join(right, keySelector, keySelector, Tuple.Create);
}
现在你可以使用这样的东西了:
class Product
{
public string ProductName { get; set; }
public string ProductCode { get; set; }
}
List<Product> list1 = ...;
List<Product> list2 = ...;
var result = list1.Join(list2, new [] { "ProductName", "ProductCode" });