1

Let's say I want to store date which cannot be changed by the user in code. For example, my application supports ten types of reports, and I want to store metadata about it. Usually, I'd use a constant dictionary for that:

Private Shared ReadOnly ReportConfigurations As New Dictionary(Of Reports, ReportMetadata)() From
{
    {Reports.Foo, New ReportMetadata("Foo Report", PaperSize.A4, 8, 12, ...)},
    {Reports.Bar, New ReportMetadata("Bar Report", PaperSize.A4, 8, 14, ...)},
    ...
}

(Obviously, I'd use Const if .NET supported constant dictionary fields and I'd use ImmutableDictionary if I weren't stuck with an older version of the framework.)

This works fine, but it gets hard to read quickly once the number of metadata fields increases (you can't see what 8 and 12 refer to unless you add named parameters, and the fields are nicely aligned only as long as you call your reports "Foo" and "Bar", which I don't). An option would be to use inline XML instead and parse it (which is quite easy if your language supports it):

Private Shared ReadOnly ReportConfigurations As XElement =
    <Reports>
        <Report Name="Foo Report" PaperSize="A4" 
                FontSizePx="8" BarcodeWidthCm="12"
                ... />
        ...
    </Reports>

but I miss the tabular structure. Ideally, I'd have something like this

 ReportName | PaperSize | FontSizePx | BarcodeWidthCm | ...
 ---------------------------------------------------------------
 Foo Report | A4        | 8          | 12             | ...
 Bar Report | A4        | 8          | 14             | ...
 ...

but adding an Excel sheet as a resource to my project and parsing it at run time seems like terrible overhead, just for a bit of increased readability.

Is there some elegant solution that I've missed?


Related question:

  • Storing data in code (This is about two-field data, for which the Dictionary solution or a resource file would work fine.)
0

4 Answers 4

4

A simple format for storing tabular data is CSV. Attach it as a resource, just like you planned to do with the excel document.

In theory you can even edit it using standard spreadsheed software, though there will problems with that:

  • CSV does not encode types, so Excel will use heuristics to detect e.g. dates, which may corrupt data that looks like a particular type but is not.
  • Excel uses different separators, date formats, decimal separators, etc. depending on the regional settings of the computer it runs on. AFAIK there is not flavour of CSV that will work with excel regardless of culture.
  • Excel uses the legacy encoding instead of UTF-8 encoding. Using tab as separator might avoid this issue.

An interesting alternative is the json-lines format, where each line is an independent json value, but software support is lacking.

3
  • 1
    Whoever is going to use this approach (which I think is appropriate for the above use case): Please do not write your own yet-another-handrolled-and-very-likely-flawed CSV parser. Grab something from Nuget. Please. It will bite you, badly, very badly ... Jul 11, 2016 at 19:49
  • @TheoLenndorff I only wrote custom exporters so far, but even parsers don't sound that difficult. As long as you use a simple state machine instead of trying to split at the separator characters, you should be fine. Jul 11, 2016 at 20:57
  • @CodesInChaos but why reinvent something that already exists? Jan 18, 2019 at 20:43
1

I think the solution you have is the right one. If the report metadata is declared in one place, it seems like that would be fairly readable? However, one way to make it more readable would be to create a builder for the ReportMetaData class. Here's an example for Java (though should apply equally well to C#): http://www.informit.com/articles/article.aspx?p=1216151&seqNum=2

1

I've seen it done with tabs after commas before so you get.

{Reports.ReallyLongFoo, New ReportMetadata("Really Long Foo Report",    PaperSize.A4,   8,  12, ...)},
{Reports.ShorterBar,    New ReportMetadata("Shorter Bar Report",        PaperSize.A4,   8,  14, ...)},

Unfortunately it fights against any automated formatting of the code block.

0

I like the idea of XML for simple things like this. If you restructure the XML the readability goes up. Something like this.

    Dim ReportConfigurations As XElement =
        <Reports>
            <Report>
                <name>Foo Report</name>
                <papaersize>A4</papaersize>
                <fontsize>8</fontsize>
                <barcodewidthcm>12</barcodewidthcm>
                <!-- etc -->
            </Report>
            <Report>
                <name>Bar Report</name>
                <papaersize>A4</papaersize>
                <fontsize>10</fontsize>
                <barcodewidthcm>14</barcodewidthcm>
                <!-- etc -->
            </Report>
        </Reports>
    '  OR
    '   ReportConfigurations = XElement.Load("path")

    Dim reportProto As XElement =
        <Report>
            <name></name>
            <papaersize></papaersize>
            <fontsize></fontsize>
            <barcodewidthcm></barcodewidthcm>
            <!-- etc -->
        </Report>

    'to add new report
    Dim newReport As New XElement(reportProto)
    newReport.<name>.Value = "new report"
    newReport.<papaersize>.Value = "Letter"
    'etc
    ReportConfigurations.Add(newReport)

    '  ReportConfigurations.Save("path")

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.