views:

523

answers:

6

I like to cleanly separate public and domain objects (so, nHibernate isn't going to help here) from each other which ends up forcing me to write a lot of code to map one object to another. What tools/plugins are out there to take the tedium of having to do manually do this mapping in .NET?m Whenever I Google this, it thinks I'm wanting to do ORM, which is not what I'm looking for. Thanks!

EDIT 19:33CST: OK, I wrote a very basic application (very quickly written code) that demonstrates what I'm looking for. I'm just wondering if there is a VS plugin that will do this for me.

VS2008 Solution

+9  A: 

You might want to give AutoMapper a try. It sounds like what you're looking for.

Kevin Pang
+1 - excellent link, thanks so much! This could save countless left-right assignment blocks in my code! :-)
marc_s
I actually looked at it before posting, but it still looks like you have to write code--I really want it to autogenerate it, even if it means I drag-and-drop points between Properties to tell it how the objects map. That would be infinitely faster than pounding out boilerplate code.
Wayne Hartman
@wayne, as long as your objects follow some naming conventions, Automapper figures out the mapping automatically. Otherwise you need to do a little more configuration up-front, but it's still a win. I'm not sure what more you'd want autogenerated?
Gabe Moothart
@Gabe Moothart, Tried it out; documentation is quite scant. Even still, I'm looking more for static code generation, than a runtime tool. There are runtime efficiencies in a direct mapping at design time, than running it through his code *each and everytime* it needs to be mapped at runtime. Does that make sense?
Wayne Hartman
Runtime efficiencies huh? Can anyone say premature optimization?
Robin Clowers
If I wasn't the person I am, I would write about the probable inaccuracy of the 'runtime efficiency' statement. But as it stands, I'm not a good person and I'll probably just say something rude.What I would like to see from Wayne is some profiling detailing how much faster it is for his static class to map than automapper. (Remember, automapper only has to take time to do the mapping once, after that it just runs the mapping). I'd put a bet on there being very little hit (after initial one-time configuration) between automapper and a static class.
mendicant
A: 

Could you not use interfaces for that?

disown
You still have to write code at some point, I'm looking for a tool to autogenerate it.
Wayne Hartman
It sounded to me like you have two views to the same data. In this situation interfaces is a solution where you only need to declare the mapping. I don't really understand why you need to _copy_ the data. I've done that, but later figured out that it was the wrong solution. Just saying. Maybe you do have your reasons.
disown
@disown that's a good explanation. I removed my downvote.
Gabe Moothart
+1  A: 

There is also an interesting project called Otis. Below is the example *.otis.xml mapping taken from the documentation page:

<?xml version="1.0" encoding="utf-8" ?> 
<otis-mapping xmlns="urn:otis-mapping-1.0">
<class name="Otis.Tests.UserDTO, Otis.Tests" source="Otis.Tests.Entity.User, Otis.Tests" >
    <member name="Id" />
    <member name="Age" />
    <member name="UserName" expression="$UserName.ToUpper()" nullValue="[unknown]" />
    <member name="FullName" expression="[$FirstName + ' ' + $LastName]" />
    <member name="ProjectCount" expression="$Projects.Count" />
    <member name="Title" expression="$Gender" >
        <map from="Gender.Male" to="Mr." />     <!-- projections -->
        <map from="Gender.Female" to="Mrs." />
    </member> 
    <member name="Birthday"  expression="$BirthDate" format="Born on {0:D}"/>
    <member name="ProjectCount" expression="$Projects.Count" />
    <member name="AvgTaskDuration" expression="avg:$Projects/Tasks/Duration" />
    <member name="MaxTaskDuration" expression="max:$Projects/Tasks/Duration" />             
</class>

To read the mapping files from the assembly:

// configure the new Configuration object using metadata of types in the current assembly
Configuration cfg = new Configuration();            // instantiate a new Configuration, one per application is needed
cfg.AddAssembly(Assembly.GetExecutingAssembly());   // initialize it

Hmm, where have I seen it before? ;)

bbmud
+1 looks very interesting, too - I also like the idea of being able to externalize the mapping into a XML configuration file if needed / appropriate
marc_s
A: 

So, seemingly dissatisfied with a runtime solution, I have written a small utility that will create the mappings in code. You can download the source below and write better error handling, etc., etc. I'd appreciate any cool modifications you make, this was made in haste, but works. Please respect that the code is being released under the LGPL.

Object To Object Mapping Utility Source Code

UPDATE 23 JUN 2009: I made some updates to the code that cleaned it up (a little bit) and also added the ability to save a mapping to a file so that you can later modify it.

Wayne Hartman
A: 

Perhaps using a language with strong meta-programming support would be appropriate? Right tool for the right job, eh?

stevenharman
@stevenharman, ya it's called c#
Omu
A: 

use ValueInjecter, with it you can map anything to anything e.g.

  • object <-> object
  • object <-> Form/WebForm
  • DataReader -> object

and it has cool features like: flattening and unflattening

Omu
The whole point, though, is not to write code because these are static mappings. The idea is that all that is happening is right to left assignment, so (IMHO) it does not merit any reflection, runtime gymnastics, et all. Bang the 'premature optimization' gong all you want, but there is *great* efficiency at doing things at compile time vs. runtime. I've seen libraries like Dozer (for Java) just chew up CPU for something as simple as a right to left assignments.
Wayne Hartman
@Wayne Hartman I haven't had any problems with the efficiency, it uses TypeDescriptor, and I wrote test where 1 million mappings are done in 2 seconds, so I don't think speed/memory/cpu is an issue here
Omu