1

As input for this problem I have a DataTable instance. For some framework functions I have to use, I need to pass rows from this DataTable as List<my_class> where properties of my_class are named like columns of the input DataTable.
Maybe a better explanation is: instead of getting a cell value like DataTableName.Rows[0]["first_column], I'd have to get it as myList[0].first_row.

This means converting strings to property names on the fly, so I thought about creating a string like this:

"namespace NewRow 
{
    class my_class
    {
        public string first_column { get; set; }
        public string second_column { get; set; }
        ...
    }
}"

then using CSharpCodeProvider to compile this string and then create a List<my_class>.

After I use var codeResult = provider.CompileAssemblyFromSource(new CompilerParameters(), codeAsString); I don't know what to do next. How do I get the new class as a type?

NOTES
I unsuccessfully tried passing List<object> to my framework functions. It doesn't matter if this list is populated with anonymous object with properly named properties or a hardcoded my_class with properly named properties, I get the same error saying that my object (from the list) doesn't contain a property named first_column.

Also note that sadly, I don't have the access to this framework functionality and cannot edit it.

Framework's function actually expects a IQueryable, but I thought it would be easier to work with a List and then convert it to IQueryable just before passing this list to the function (I can do this by using my_list.AsQueryable() function), but if it helps solve the problem, it's ok to use the IQueryable.

QUESTIONS

Am I on the right track with CSharpCodeProvider?
If so, how do I create a List<my_class> on the fly?
Is there another way I'm not aware of for doing this kind of conversion?

Monset
  • 648
  • 5
  • 25
  • 1
    Can you clarify: does the `my_class` exist in code and you want to map it to the table loading properties from the columns? or are you creating the `my_class` *to match* the table, without knowing it in advance? if the latter: *why* do you want to create the `my_class` on the fly? what problem are you trying to solve there? (it matters); if the former: [Dapper has your back](https://gist.github.com/mgravell/2de14d8fb25763efc1f508d41b15e646) – Marc Gravell Feb 07 '20 at 11:26
  • Regarding your first note: If you are using a List, you have to cast the elements to access the properties: ((my_class)my_list[0]).first_column; – Zavog Feb 07 '20 at 13:31
  • @MarcGravell the input and output are set by requirement. Sadly I cannot influence this requirement, so this is one solution I'm coming up with, as you can see, I would appriciate help. – Monset Feb 07 '20 at 13:55
  • @Zavog casting is done in framework, as in - I cannot access it (sad emoticon) – Monset Feb 07 '20 at 13:57
  • But which are you doing: creating a new class at runtime to match the `DataTable` (possible but of questionable value) or copying the `DataTable` rows to an existing (compile time) class with field names matching the column names (also possibly, probably more useful, though that begs the question: why do you have a `DataTable`)? – NetMage Feb 07 '20 at 20:48
  • More specifically, is `my_class` defined in the source code of the program somewhere? – NetMage Feb 07 '20 at 20:49
  • @monset the input and output usually is defined outside of our control. I simply asked you to clarify the nature of the output, as it impacts the solution. Can you please answer the question I actually asked? – Marc Gravell Feb 07 '20 at 21:59
  • @MarcGravell sorry, I kinda glossed over the question, probably just like you glossed over mine, so again: the second one. `my_class`'s property names should match the names of the columns in `DataTable`. I cannot predict the number of these columns or their names, because the `DataTable` will be created by other developers. They will be writing scripts with `Run()` function that will return `DataTable`, and that's my input. For further filtering of input, because of the mentioned framework I'm working in, I need to convert this data into `List`... – Monset Feb 08 '20 at 22:40
  • ...where `my_class` has the properties named by columns of the mentioned `DataTable`. I hope it's clear now. – Monset Feb 08 '20 at 22:41
  • K. So *why* do you want `my_class` as a class? What purpose does that serve? What problem does it solve? Usually a class is a build-time thing, and a DataTable with flexible columns is purely runtime. So: you'd have to do this with emit. Which can be done, but it sounds like a really really bad solution. And it is an absolute *ton* of work. So: again, *why* are you trying to generate a class here? The answer to this really really really matters. I'm pretty sure that you don't actually need to, and that better options exist that don't involve that. – Marc Gravell Feb 09 '20 at 19:27
  • In particular: nobody else can make any sensible use of a type that is emitted at runtime. You can't code against it, because it doesn't exist at build. So that leaves only library consumers (reflection, etc). And usually, library consumers have *other ways of solving this problem*. For example, serializers often take dictionaries for this scenario. UI tools - well, they usually work with PropertyDescriptor. But DataTable already works with PropertyDescriptor, so: nothing to do - just feed it your DataTable. So again: *why*? It really, really, really matters. – Marc Gravell Feb 09 '20 at 19:30
  • I mean, sure you *can* emit a type at runtime, and use reflection to create a List-T for that type, but you can't return it *as* a List-my_class, because you can't express my_class on an API because *it doesn't exist at build*. So now you're returning a non-generic IList and the calling code has to use reflection (they can't even use "dynamic" because they don't know the members by name in advance). Nobody wants to use reflection here. There is almost certainly a better approach if you can explain *why*. – Marc Gravell Feb 09 '20 at 19:34
  • To put it in other terms: it feels like you're asking the best way to hammer screws into wood. We'd all love to tell you about either screwdrivers or nails, because it sounds like you're trying very hard to do something that is just fundamentally a bad idea. – Marc Gravell Feb 09 '20 at 19:35
  • I understand how bad this method is. I already lost a couple of working days trying to not create class on the fly, but my input and output are set. As for why, the function I need to use to convert my data from input (`DataTable`) to something visible by user is inside the company's framework that I cannot change. I know how bad this solution is, and I wouldn't be here asking for help if ti could be done differently. A really bad, but for now the only solution. And your analogy about hammering screws is perfect description for this solution. – Monset Feb 10 '20 at 09:44
  • I even thought of copying the mentioned framework function and modifying it so that it works with `DataTable`, but this function goes too deep for me to simply copy only that one function. There's a whole infrastructure beneath it. – Monset Feb 10 '20 at 09:48

0 Answers0