C# 在GroupBy中将Func表达式用作参数

C# 在GroupBy中将Func表达式用作参数,c#,linq,generics,C#,Linq,Generics,我正在创建一些统计数据,说明有多少来自不同部门的员工是特定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

我正在创建一些统计数据,说明有多少来自不同部门的员工是特定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
我有一个拥有以下成员的班级组织单元:

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用户对象,包含成员Org0、Org1和Org2

要计算我使用GroupBy的每个组织单元/级别中有多少员工,问题是我无法确定如何使用通用的group by表达式,因此我需要为每个组织级别使用一个方法。如下图所示:

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;
}
私有静态IEnumerable GetLevel0(IEnumerable persons),其中T:OrgUnit,new()
{
var level0=persons.Where(x=>!string.IsNullOrEmpty(x.Org0))
.GroupBy(ac=>new
{
ac.0
})
.选择(ac=>
{
返回新的T
{
Org0=ac.Key.Org0,
顾问=ac.Count(x=>x.EmpGroup.Equals(“顾问”),
Employees=ac.Count(x=>x.EmpGroup.Equals(“Employees”))
};
});
回报水平0;
}
私有静态IEnumerable GetLevel1(IEnumerable persons),其中T:OrgUnit,new()
{
var level1=persons.Where(x=>!string.IsNullOrEmpty(x.Org1))
.GroupBy(ac=>new
{
ac.0,
ac.Org1
})
.选择(ac=>new T
{
Org0=ac.Key.Org0,
Org1=ac.Key.Org1,
顾问=ac.Count(x=>x.EmpGroup.Equals(“顾问”),
Employees=ac.Count(x=>x.EmpGroup.Equals(“Employees”))
});
回报水平1;
}

我的问题是,我如何使用泛型来只有一个方法,而不是一个方法GetLevel pr org level

> P>你可以做到这一点,但有划痕和一些合同,第一个合同是你知道有多少个ARG列存在,并在此假设下考虑元组项目的数量,在这个例子中,ARG的数量是3:

元组的属性之一是相等,它由每个组件的默认对象相等比较器确定

如果您想要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;
}
公共静态IEnumerable GetLevel(IEnumerable persons,
Func(集团)
其中T:OrgUnit,new()
{
风险等级1=人。其中(x=>
!string.IsNullOrEmpty(组(x).项目2==null?组(x).项目1:
(第(x)组第3项??第(x)组第2项)
.GroupBy(组)
.选择(ac=>new T
{
Org0=ac.Key.Item1,
Org1=ac.Key.Item2,
Org2=ac.Key.Item3,
顾问=ac.Count(x=>x.EmpGroup.Equals(“顾问”),
Employees=ac.Count(x=>x.EmpGroup.Equals(“Employees”))
});
回报水平1;
}

您不能使用匿名类型。所以您想要一个函数
getnthlever
?这将根据它从
Org0
OrgN
找到的多少
OrgN
属性进行分组?而且,我不确定在这里使用泛型与让你的
GetLevel0
返回
IEnumerable
相比,你会获得多少收益。很酷,效果非常好。对于阅读本文的其他人,要使用该方法,我必须创建以下Func来使用它:Func k=person=>newtuple(person.Org0,person.Org1,person.Org2);