views:

52

answers:

3

I am using FileHelpers to parse CSV files whose structure is unknown using the following code:

            string cd = string.Format(@"[DelimitedRecord(""{0}"")]
                                        public sealed class ImportClass {{
                                            [FieldQuoted('{1}')]
                                            public string[] Fields;
                                        }}", _delimiter, _quote);
            Type t = DelimitedClassBuilder.ClassFromString(cd);

            var engine = new FileHelperAsyncEngine(t);

            engine.BeginReadFile(filename);
            object record;
            while ((record = engine.ReadNext()) != null) {

            }

            engine.Close();

This seems to work just fine. When I step through it with the debugger, record is an object of type ImportClass and the Fields field is correctly filled with data from the file.

The problem I have is how do I actually extract that data? I cant cast record to an ImportClass since that type is not known at compile time. Do I really need to use reflection or is there a simpler way to do this?

+1  A: 

Honestly the simplest way I can think of would be use the IronPython. Construct the string of code and pass it a python engine. We replaced a tonne of reflection with the DLR and IronPython.

Or as you say, you can reflection.

Edit: To reflect comments: You only need to include the 2 iron python assemblies as references. It isn't that hard. Honestly. Its not about installing a boat load other stuff.

Preet Sangha
You can't possibly be serious. The "simplest" way would be to install, learn, and deploy an entire new language, rather than write 2 lines of Reflection?
Aaronaught
I've never done anything like this, but I already have IronPython installed and deployed. I've used Python before. I've never used reflection before. So in my case, it would be the simplest. :) It's all a matter of perspective.
Dave
@Dave: When all you have is a hammer, everything looks like a nail. IMO the fact that *you* already have a particular tool installed is not a justification for giving an answer that depends on a tool that is not standard and that the OP in all likelihood does *not* have. **Especially** when it's a Reflection question that's about simple method or property access.
Aaronaught
Fair enough! :) I need to start reading up on reflection, but there's still so much other stuff that I need to tackle first!
Dave
If I was using IronPython, I would have simply used the csv module.
Ferruccio
The DLR stuff from MS is incredibly easy only to use. As a perspective I used find reflection a lot more hard that the simplicity of the DLR. However I would add the linq 2 objects makes reflection a lot easier than in .net 3 and below. Re using Python. we use it to allow custom code to be written for our products we have no ideas of the types and thus the object graphs that customers will create. But we still need to get to the data. Before the DLR we used reflection and it was lot of code to write.
Preet Sangha
A: 

There's probably a clean way of doing this exposed by the library you're using. Nevertheless, here is a general answer using Reflection:

Type t = ...  // You already have this
PropertyInfo fieldsProperty = t.GetProperty("Fields",
    BindingFlags.Public | BindingFlags.Instance);
string[] fields = (string[])fieldsProperty.GetValue(record, null);

Edit:

This library appears to have methods that allow you to read the file into a DataTable instead, and this seems to be their recommended approach. The example shown on this page is:

DataTable dt = engine.ReadFileAsDT("test.txt"); 

This is probably simpler and faster than using Reflection.

Aaronaught
That worked with a minor change. Since I was using fields instead of properties, I needed to use FieldInfo and GetField().
Ferruccio
Some of the files I'm processing can get really big and I would rather not have two copies in memory (DataTable + my data structure). Looking at DataTable, however, makes me think it may have been more appropriate to use to store the data in the first place. So I may eventually refactor to use a DataTable and will be able to use the simpler solution.
Ferruccio
A: 

declare class in your code. no need to use reflection here.

Adeel
That was my original approach. The problem is that the delimiter and quote characters are set using attributes and there doesn't seem to be a way to set them after an ImportClass object is instantiated.
Ferruccio