Filter List and Display Type members with specified attribute

One of the recent questions that was intriguing (for me) in Stackoverflow was the need to Process a List and while displaying the result, display only the properties that are decorated with a specific attribute.

Let me explain with an example. Consider the following Entity.

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; }
}

For a List<Employee>, the expected result would display only “BusinessVertical”, “Region”, and “BusinessUnit” in the result. Let’s begin by creating a mock sample data to test it.

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"},
};

Just to make things interesting, we would add restriction that the result needs to be Sorted By Region and Then by BusinessUnit. A LINQ solution would have been ideal, but unfortunately, I couldn’t go all the way with LINQ. But here is the solution I could suggest.
The first step, obviously was to get the List of Properties that has the required Attribute, which we can achieve using Reflection.

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());

Where CreateObject is defined as

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;
}
}

Since even anonymous types needs to have Property Names defined in compile time, the only solution to create a Dynamic Type (including property names) was using ExpandoObject.
This would give you the desired output as enclosed in the screenshot.

Capture

Again, this is the solution I could arrive at, there would be better ones. I would certainly be interested to know a better solution. If anyone would like to follow the OP in question, please follow it StackoverFlow

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s