My name is Alex and I just created an object-2-object mapper.
I know, there's so many of them already. But still... The reason I thought the world deserves another one is speed. Most mappers (including the famous AutoMapper) rely on Reflection these days, at least to some extent. And Reflection is slow. It uses object's meta-data to locate and invoke a member, which is about three times slower than invoking the member directly.
It's not a big deal when you run it once or twice. But object mapping often happens inside a
foreach loop, that can have thousands of iterations.
First, a quick explanation of what "expressions" are.
Expressions have been out there since .NET 4.0 and C# 3.0. An
Expression object is simply a reference to an executable line of code. The code can be written explicitly at design time or built at run time. And even compiled to MSIL/CIL to run faster.
Take a lambda function:
Func<int, int, int> add = (x, y) => x + y;
Pretty common. Let's further wrap that into an
Expression<Func<int, int, int>> addExpression = (x, y) => x + y;
The Expression here is not just executable code, it's a data-object that holds meta information about it.
Console.WriteLine((addExpression as BinaryExpression).Body);
"(x + y)"
We've just built an expression by writing some explicit code and then creating an
Expression object out of it.
But the cool part is that this works the other way around too - you can build an expression first, and then compile it back to executable code.
You've just seen how to build an expression from actual code. Now let's do it in reverse - let's build code from meta-info and expressions.
Let's say you have two
PropertyInfo objects that hold meta-information about a type's properties.
PropertyInfo prop1; PropertyInfo prop2;
You can simply build an expression that will assign one property to another.
var e = Expression.Assign(Expression.Property(srcObj, prop1), Expression.Property(destObj, prop2)));
Now create a lambda function out of it:
var lambda = Expression.Lambda<Action<Type1, Type2>>(e, srcObj, destObj); var action = lambda.Compile(); //now we can call the "action" action(object1, object2); //this will run "object1.prop1 = object2.prop2"
PropMapper is built exactly like this. It generates an expression tree, which is then compiled and cached in a static variable.
It does add a little overhead of enumerating the type's properties (still very fast) but then it's almost as fast as manual "property-by-property" assignment.
BECAUSE IT IS!
It's an expression tree, that generates the code and compiles it to MSIL (and native code later).
It takes 25 milliseconds to run over 100k iterations (manual mapping takes 10ms)
Check out the project (and benchmarks) here.
Dapper.NET uses a similar approach, but it's more of an ORM than a property mapper, so in case you just need a short, simple and flat object mapper - give it a try.