Background

I recently came across the need to be able to assign values of one type to values of another type that I had no control over. A vendor had provided an assembly which exposed a proxy that accepted message types that had a vastly different structure to the types we used internally. A quick view of the assembly through Reflector revealed it to be very badly written (and I do mean horrible). I wrote this little utility to allow our software to map message types we used internally to message types exposed by the third party assembly. While I implemented this for my specific needs, I thought I might as well share it with the rest of the world in the event that somebody, somewhere might face a similar problem and find it useful.

Design Goals

I wanted a simple utility with a single call to be able to assign ("map") the values of one type to another. I wanted it to be both flexible and extensible. I had considered juggling with delegates and serialization and various other tricks with Generics before I came up with what, I think, is a simple solution. I didn't want to jump through too many hoops to get the mapping done, and wanted to have as simple a call as possible at the point where the mapper was needed. I decided to list the goals as:

How it Works

Under the hood, Mapper uses a handful of interfaces and Generics.

IMappable

Very simple, empty interface. Allows a class to be the input to the mapping. This would be the type which you do have control over. It's an empty interface deliberately so that there are no conditions to satisfy in order to use it.

publicinterface IMappable {}

IMappingProvider

Provides the service contract for components which will provide the mapping implementation. The method expects a type argument to be supplied for its usage. This is the heart of the entire utility. It's important that the generic type is part of the method and not part of the interface declaration.

publicinterface IMappingProvider
{
T Map<T>(IMappable input);
}

ConcreteMappingProvider

Implements the specific mapping between IMappable to one or more types. Note: This ConcreteMappingProvider is given here only as a demonstration on very basic types. You'll notice that it implements the IMappingProvider interface with the generic <T> type expected as the result type. The interface implementation (public method) passes the work on to a private method which will return the concrete type (i.e., the type which you have no control over). It asks the private method to return the result as an object; this is because casting directly from the concrete type to <T> is illegal. Casting to <T> from object, however, is legal. Thus, you should have the expected type returned with no boxing overhead.

Dependency Injection

Although DI is not essential to using this utility, I made provision for it by separating the specific implementation from the facade. Using the DI container/framework of your choice, you can register/resolve the specific providers as you see fit. I use the Windsor container, so the download sample looks similar to:

Extending the Solution

To extend the solution to suit your needs, the least you'd have to do is write your own component which implements IMappingProvider. While this provider could run into a few hundred lines of code (depending on what you need to map), that is just about all you'd need to do.

Conclusion

As mentioned above, this is a lightweight type mapper which is flexible, simple, and extensible. I hope it finds a happy home in your own code.

I think you'd be opening yourself up to data loss, but willing to test it out.

But fortunately we have the nanny-state politicians who can step in to protect us poor stupid consumers, most of whom would not know a JVM from a frozen chicken. Bruce PiersonBecause programming is an art, not a science. Marc CliftonI gave up when I couldn't spell "egg". Justine Allen

While the code & technique since fine, but it's unclear what the advantage of it is. You never show the use case where the infastructure is useful. You only show mapping a TypeA to TypeB --- itself a fairly simple task. Does this let me also convert a TypeC to a TypeB, or perhaps convert a TypeA into a TypeC?

Does this let me also convert a TypeC to a TypeB, or perhaps convert a TypeA into a TypeC?

Short answer - yes, but that depends on how much code you're willing to write for the IMappingProvider implementor. This is supposed to be a SIMPLE mapping utility so if it looked like we'd be writing thousands of lines of code to do the mapping we likely wouldn't have gone this route.

Longer answer - Theoretically, you could map any one type to any other. In the article, I've presented TypeA as an object which I have control over (i.e. I am able to modify the type and its members) and TypeB as a type which I have no control over e.g. a specific type defined by a third party that is expected as the argument to method. That said, it's entirely possible to map between two types that you have no control over by introducing a wrapper that inherits from IMappable which you could then pass through the concrete implementation of IMappingProvider.

James Curran wrote:

show the use case where the infastructure is useful.

I'll use the scenario for which I wrote this.

In our software, we have internal message types which report on business rule violations and process state, etc. We had to introduce a means to publish these messages to a third party tool. This tool is fugly. They expose a proxy which expects one of their own defined types as an argument. It's an overloaded method that expects different types for different functionality. This proxy never returns any information, it's meant to be a 'fire & forget' solution.

The types defined by the third party make very little logical sense. They have types which are literally collections of collections of collections, members and code repeated all over the show, nasty error handling and general mayhem. Even still, my job is not to criticize this code but to make sure our software plays nicely with it.

Rather than pollute our code with logic that this third party tool needs, I introduced this simple mapping layer which allows us to map to the specific types expected by the proxy. This way, when it comes to calling the proxy, I have a simple call to the mapper to return what I want when I need it, e.g. something like:

I hope that clarifies the use case somewhat. Of couse, I can't publish our exact code but I'm hoping this is a 'near-enough' simile.

But fortunately we have the nanny-state politicians who can step in to protect us poor stupid consumers, most of whom would not know a JVM from a frozen chicken. Bruce PiersonBecause programming is an art, not a science. Marc CliftonI gave up when I couldn't spell "egg". Justine Allen

Thanks for the link to Automapper, I didn't know this existed until you posted this link.

Cheers,D.

But fortunately we have the nanny-state politicians who can step in to protect us poor stupid consumers, most of whom would not know a JVM from a frozen chicken. Bruce PiersonBecause programming is an art, not a science. Marc CliftonI gave up when I couldn't spell "egg". Justine Allen

No need to apologize, I had no knowledge of Automapper before this evening. I'm happy with my solution & still glad I wrote this article. I'll give Automapper a try sometime & see whether I prefer it or my own.

But fortunately we have the nanny-state politicians who can step in to protect us poor stupid consumers, most of whom would not know a JVM from a frozen chicken. Bruce PiersonBecause programming is an art, not a science. Marc CliftonI gave up when I couldn't spell "egg". Justine Allen