I'm writing a specific kind of object-mapper. Basically I want to convert from a DataTable
that has the fields a
, b
and c
to an object that has properties a
, b
and c
(the class of the object will be written by hand). There will be many different DataTables and many different classes that they will need to map to, so I want to make a generic mechanism that performs this data copying. Basically, I want the following function:
public T Map<T>(DataTable t) where T: new() { ... }
Now, I can do this with Reflection, but that's slow. This function will be at the core of the framework and will be used often. So I'm thinking about dynamic code generation. The first time this method is run on a specific T
it will perform the necessary reflection and emit an anonymous method that does all the appropriate mapping. The next time it will just run that code. This should be as performant as possible.
Just one problem - I've never emitted code at runtime. How do I do that? I looked at Expressions
, but they can only do, well, expressions, not a series of statements.
Then there's CodeDOM and CSharpCodeProvider
. That sort of works - I can generate C# code as a string, compile it on-the-fly and then get a reference. However it involves the C# compiler and generates a whole new in-memory assembly. Sounds a bit... heavyweight for one simple method.
Is there some simpler way? Something that generates a lightweight, anonymous method not attached to any assembly (or attached to an existing assembly)?
OK, since people asked for an example.
Here's a class, written by hand
class MyBusinessObject
{
public int a;
public string b { get; set; }
}
Here's a DataTable, prepared by hand (in real life, this will come from an external library):
DataTable t = new DataTable();
t.AddColumn("a", typeof(int));
t.AddColumn("b", typeof(string));
t.AddRow(42, "Meaning");
Here's the method that should be generated on the fly:
(DataRow drow, MyBusinessObject o) =>
{
o.a = (int)drow["a"];
o.b = (string)drow["b"];
}
I've omitted some other stuff I need for brevity, but that's the meat of the issue.