Question

I am using .NET 4.0, C# 4.0 in Visual Studio 2012 with Code First and Entity Framework.

I have a set of classes that I want to use as the basis for various report. The data for the reports is held in an SQL database. An example class is:

public class DocumentTrackerChaseReport
{
    public int DocumentTrackerChaseReportID { get; set; }
    public int CaseID { get; set; }
    public int DocumentID { get; set; }

    [Description("Case ID")]
    public String CaseIdentifier { get; set; }
    [Description("Document type")]
    public String DocumentCategory { get; set; }
    [Description("Contact")]
    public String ContactName { get; set; }
    [Description("Phone number")]
    public String ContactPhoneNumber { get; set; }
    [Description("email address")]
    public String ContactEmail { get; set; }

    public TrackingActionType TrackingActionType { get; set; }
}

The Description attributes acts both as the headers for the report and also to indicate which properties are to be excluded from the report.

I have a method to extract the headers as a string array from this question

I can also generate a method which checks to see if a field/property has a description attribute.

The key ingredient I am missing is a straightforward and generic way to generate each line of the report omitting the fields that don't have this attribute. I can iterate through all of the fields using reflection and checking for the attribute for each line of the report but that seems long winded.

Is there an elegant solution to this?

Was it helpful?

Solution

You can pre-cache the names of the properties that you are interested in (i.e. the ones with the description attribute) and then use those to only grab the values you are interested in.

I've hacked together a quick example of this, it's not the most robust code but it shows the general idea (makes a lot of assumptions about ordering) and only fetched the attributes once.

(Edit: realised we only needed to call GetProperties once for everything).

var whitelist = typeof (DocumentTrackerChaseReport)
    .GetProperties()
    .Where(x => Attribute.IsDefined(x, typeof (DescriptionAttribute)));

var rows = things.Select(x => whitelist.Select(y => y.GetValue(x) ?? ""));

This will give you an IEnumerable<IEnumerable<object>>, or in other words, a list of rows and for each row, a list of columns (with the value of each column being an object).

You could then iterate through this as follows (pseudo code)

foreach (var header in whitelist) {
    // print column of header row
}

foreach (var row in rows) {
    foreach (var col in row) {
        // print an individual cell
    }
    // break for a new row
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top