简体   繁体   English

来自类的C#4.0通用报告生成器

[英]C# 4.0 Generic report generator from a class

I am using .NET 4.0, C# 4.0 in Visual Studio 2012 with Code First and Entity Framework. 我在Visual Studio 2012中使用Code First和Entity Framework使用.NET 4.0,C#4.0。

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. 报告的数据保存在SQL数据库中。 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. Description属性既充当报告的标题,又指示要从报告中排除的属性。

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? 是否有一个优雅的解决方案?

You can pre-cache the names of the properties that you are interested in (ie the ones with the description attribute) and then use those to only grab the values you are interested in. 您可以预先缓存您感兴趣的属性的名称(即具有description属性的名称),然后使用这些名称仅获取您感兴趣的值。

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). (编辑:意识到我们只需为所有内容调用一次GetProperties)。

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). 这将为您提供IEnumerable<IEnumerable<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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM