在GroupBy中使用函数表达式作为参数
本文关键字:表达式 参数 函数 GroupBy | 更新日期: 2023-09-27 18:03:43
我正在创建一些统计数据,显示来自不同部门的多少员工是特定Active Directory组的成员。为此,我从ad中检索所有组成员,并按部门/组织级别对其进行分组。
我希望结果看起来像这样:
Org0 | Org1 | Org2 | Count
CFO | | | 27
CFO | AA | | 11
CFO | AA | JJ | 11
CFO | BB | | 16
CFO | BB | CC | 4
CFO | BB | DD | 12
我有一个类OrgUnit,它有以下成员:
public int Employees { get; set; }
public int Consultants { get; set; }
[NotMapped]
public int Total => Employees + Consultants;
public string Org0 { get; set; }
public string Org1 { get; set; }
public string Org2 { get; set; }
我还有一个Person类,它是派生的AD User对象,它包含成员Org0、Org1和Org2。
要获得每个组织单位/级别中有多少员工的计数,我使用GroupBy,问题是我无法弄清楚如何通过表达式使用通用组,因此我需要为每个组织级别提供一个方法。如下所示:
private static IEnumerable<T> GetLevel0<T>(IEnumerable<Person> persons) where T : OrgUnit, new()
{
var level0 = persons.Where(x => !string.IsNullOrEmpty(x.Org0))
.GroupBy(ac => new
{
ac.Org0
})
.Select(ac =>
{
return new T
{
Org0 = ac.Key.Org0,
Consultants = ac.Count(x => x.EmpGroup.Equals("Consultant")),
Employees = ac.Count(x => x.EmpGroup.Equals("Employee"))
};
});
return level0;
}
private static IEnumerable<T> GetLevel1<T>(IEnumerable<Person> persons) where T : OrgUnit, new()
{
var level1 = persons.Where(x => !string.IsNullOrEmpty(x.Org1))
.GroupBy(ac => new
{
ac.Org0,
ac.Org1
})
.Select(ac => new T
{
Org0 = ac.Key.Org0,
Org1 = ac.Key.Org1,
Consultants = ac.Count(x => x.EmpGroup.Equals("Consultant")),
Employees = ac.Count(x => x.EmpGroup.Equals("Employee"))
});
return level1;
}
我的问题是,我怎么能使用泛型只有一个方法,而不是一个方法。
你可以这样做,但需要一些合约,第一个合约是你知道有多少个参数列存在,并基于这个假设考虑元组元素的数量,在这个例子中,参数的数量是3:
Tuple的属性之一是相等性是由每个组件的默认对象相等比较器决定的。[MSDN]
如果你想要Level1,那么用新的Tuple.Create(p.Org0, null, null)
填充组,如果想要Level2,那么组是Tuple.Create(p.Org0, p.Org1, null)
,等等。
public static IEnumerable<T> GetLevel<T>(IEnumerable<Person> persons,
Func<Person, Tuple<string, string, string>> group)
where T : OrgUnit, new()
{
var level1 = persons.Where(x =>
!string.IsNullOrEmpty(group(x).Item2 == null ? group(x).Item1 :
(group(x).Item3 ?? group(x).Item2)))
.GroupBy(group)
.Select(ac => new T
{
Org0 = ac.Key.Item1,
Org1 = ac.Key.Item2,
Org2 = ac.Key.Item3,
Consultants = ac.Count(x => x.EmpGroup.Equals("Consultant")),
Employees = ac.Count(x => x.EmpGroup.Equals("Employee"))
});
return level1;
}