仅选择具有特定属性的匿名成员

时间:2018-12-16 12:24:15

标签: c# linq anonymous-function

我有一个名为Employee的类(这只是其中的一部分):

public class Employee
{        
    public int ID { get; set; }

    public string Place { get; set; }

    [IncludeinReport]
    public string BusinessVertical { get; set; }

    [IncludeinReport]
    public string Region { get; set; }

    public string Country { get; set; }

    [IncludeinReport]
    public string BusinessUnit { get; set; }
}

我想使用Linq只选择具有IncludeinReport属性的属性。下面是我现在使用的linq,我要做的只是手动选择具有以下属性的属性:

                 var report = from c in Employee                
                 orderby c.Region, c.BusinessUnit
                 select new
                 {
                     c.BusinessVertical,
                     c.Region,
                     c.BusinessUnit,
                 }

但是我希望能够做这样的事情:

                 var report = from c in Employee                
                 orderby c.Region, c.BusinessUnit
                 select c.members.hasattribute(IncludeinReport)

1 个答案:

答案 0 :(得分:0)

不确定这是否是最好的方法,但是您可以执行以下操作。

对象

public class Employee
{        
    public int ID { get; set; }

    public string Place { get; set; }

    [IncludeinReport]
    public string BusinessVertical { get; set; }

    [IncludeinReport]
    public string Region { get; set; }

    public string Country { get; set; }

    [IncludeinReport]
    public string BusinessUnit { get; set; }
}

public class IncludeinReport:Attribute
{
}

样本数据

var list = new List<Employee>
    {
        new Employee{ID = 1, Region = "Europe", BusinessUnit="Software", BusinessVertical = "Sample1"},
        new Employee{ID = 1, Region = "Asia", BusinessUnit="Software", BusinessVertical = "Sample1"},
        new Employee{ID = 1, Region = "Asia", BusinessUnit="Hardware", BusinessVertical = "Sample1"},
        new Employee{ID = 1, Region = "Europe", BusinessUnit="Software", BusinessVertical = "Sample1"},
        new Employee{ID = 1, Region = "Asia", BusinessUnit="Telecom", BusinessVertical = "Sample1"},
        new Employee{ID = 1, Region = "Europe", BusinessUnit="Software", BusinessVertical = "Sample1"},
    };

对于以上内容,您可以查询如下。您需要获取具有必需属性的属性。此属性列表用于查询数据。最后,您可以使用ExpandoObject创建所需的类型。

var properties =  typeof(Employee).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(IncludeinReport))).Select(v=>v);
var intermediate = list.OrderBy(c => c.Region).ThenBy(x=>x.BusinessUnit).SelectMany((x,index)=> properties.Select(v=> new {GroupId = index, Dict = new KeyValuePair<string,object>(v.Name, v.GetValue(x))})) ;
var resultList = new List<ExpandoObject>();

 foreach(var item in intermediate.GroupBy(x=>x.GroupId))
 {
    resultList.Add(CreateObject(item.ToList().Select(x=>x.Dict)));
 }

其中CreateObject定义为

ExpandoObject CreateObject(IEnumerable<KeyValuePair<string,object>> kvps)
{
    dynamic returnValue = new ExpandoObject();
    var dict = returnValue as IDictionary<string, object>;
    foreach (var kvp in kvps)
    {
        dict.Add(kvp.Key, kvp.Value);
    }
    return returnValue;
}

输出

enter image description here

更新

您可以对CreateObject使用扩展方法,这会使它易于阅读。

public static class Extensions
{
    public static ExpandoObject CreateObject(this IEnumerable<KeyValuePair<string,object>> source)
    {
        dynamic returnValue = new ExpandoObject();
        var dict = returnValue as IDictionary<string, object>;
        foreach (var kvp in source)
        {
            dict.Add(kvp.Key, kvp.Value);
        }
        return returnValue;
    }
}

此后,查询变为。

var properties =  typeof(Employee).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(IncludeinReport))).Select(v=>v);
var intermediate = list.OrderBy(c => c.Region).ThenBy(x=>x.BusinessUnit).SelectMany((x,index)=> properties.Select(v=> new {GroupId = index, Dict = new KeyValuePair<string,object>(v.Name, v.GetValue(x))})) ;
var resultList = intermediate.GroupBy(x=>x.GroupId).Select(x=>x.ToList().Select(c=>c.Dict).CreateObject());