2

First of all, please forgive if I am way off on this as I am somewhat new to .net, anonymous types, and LINQ. Frankly I'm struggling a bit and plan to do a lot of learning over the next month on the topic. I know enough to know what I have come up with is not the right way.

I've been given a project to create various delimited output formats deriving from a standard report feed that has been in existence for some time. There is already a framework in place for this and I am simply adding more formats and a few new output mechanisms. (Some of the details that follow are likely irrelevant, but in the interest of clarity I will include.)

A query from the data tier returns an LLBLGEN TypedList. A LINQ query is then applied to create the various feed output formats resulting in an IEnumerable anonymous object. As part of my project I am then to take that object and output it as a comma delimited file.

By reviewing the examples below and some others I've been able to kludge together a working function, but I am certain that it is in no way the right way to accomplish the task (uses reflection, etc.). That said, the "right way" eludes me! Even a pointer in the right direction would be quite helpful.

In c# convert anonymous type into key/value array?

A dictionary where value is an anonymous type in C#

Private Sub SendExport(feed As IEnumerable, filename As String)

    Dim delimited As New StringBuilder

    Dim type = feed(0).GetType
    Dim props = type.GetProperties
    delimited.AppendLine(String.Join(",", props.Select(Function(p) p.Name).ToList))

    For Each item In feed
        Dim itemType = item.GetType
        Dim typeProps = itemType.GetProperties
        delimited.AppendLine(String.Join(",", typeProps.Select(Function(p) p.GetValue(item)).ToList))
    Next

    Debug.WriteLine(delimited.ToString)

    Response.Clear()

    Response.AddHeader("Cache-Control", "must-revalidate")
    Response.AddHeader("Pragma", "must-revalidate")
    Response.AddHeader("Content-type", "application/vnd.ms-excel")
    Response.AddHeader("Content-disposition", String.Format("attachment; filename={0}.csv", filename))
    Response.Write(delimited.ToString)
    Response.End()

End Sub
Community
  • 1
  • 1
user1646212
  • 21
  • 1
  • 3
  • You could use a `DataTable` instead. Then you don't need to use reflection. – Tim Schmelter Nov 13 '12 at 21:03
  • Is there an easy way to get from anonymous type or linq query result to a datatable? – user1646212 Nov 13 '12 at 21:10
  • You should not pass an anonymous type outside of the scope of a method, use it directly or use another type from the beginning. What kind of Linq query is it, Linq-To-Sql? Note that you also can use `Linq-To-DataTable` if the data is already in memory (f.e. via `DataAdapter.Fill(DataTable)`). You could also use a custom base class for all your other classes. – Tim Schmelter Nov 13 '12 at 21:15

2 Answers2

0

I'm no expert in VB, but I think you can remove the following lines out of the loop:

Dim itemType = item.GetType
Dim typeProps = itemType.GetProperties

And simply reuse the props list again:

For Each item In feed
    delimited.AppendLine(String.Join(",", props.Select(Function(p) p.GetValue(item)).ToList))
Next
code4life
  • 15,655
  • 7
  • 50
  • 82
0

This question is quite old, but in the interest of potentially helping the next person I thought I'd provide the answer I eventually came to in my own learning and research.

In short and quite simply, Tim Schmelter had it right in his comment to my original request:

You should not pass an anonymous type outside of the scope of a method, use it directly or use another type from the beginning.

What I was attempting to accomplish was fundamentally incorrect from a design perspective and basically a misuse of the anonymous type. The correct "answer" in my case was to simply refactor the reporting tier to use strongly-typed classes across the board. LINQ queries populate the classes directly, etc. Was a relatively small effort and made things much cleaner in the end.

user1646212
  • 21
  • 1
  • 3