Click here to Skip to main content
14,265,815 members

Generic Type Mapping

Rate this:
4.42 (10 votes)
Please Sign up or sign in to vote.
4.42 (10 votes)
18 Dec 2010CPOL
A utility to assign the values of one type to another.


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:

  1. Flexible
  2. Extensible
  3. Simple
  4. DRY (i.e., Don't Repeat Yourself)
  5. Support for IoC (although not a pre-requisite)

In the end, I ended up with something like this in my client code:

Mapper mapper = new Mapper(provider);
TypeB typeB = mapper.Map<TypeB>(typeA);

How it Works

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


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.

public interface IMappable {}


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.

public interface IMappingProvider
    T Map<T>(IMappable input);


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.

public class ConcreteMappingProvider : IMappingProvider
    public T Map<T>(IMappable input)
        object result = map(input as TypeA);
        return (T)result;

    private TypeB map(TypeA input)
        TypeB result = new TypeB();
        result.StringX = input.StringA;
        result.intY = input.IntB;
        result.StringZ = input.GuidC.ToString();
        return result;


Simple facade to call the specific implementation of IMappingProvider. This the facade that you call as needed to return the specifically mapped type that you are after.

public class Mapper
    public IMappingProvider MappingProvider { get; private set; }

    public Mapper(IMappingProvider provider)
        this.MappingProvider = provider;

    public T Map<T>(IMappable input)
        return MappingProvider.Map<T>(input);


Sample Types

These are the sample types used in this article. Notice that TypeB does not inherit from IMappable. This would be the type that you have no control over.

public class TypeA : IMappable
    public string StringA { get; set; }
    public int IntB { get; set; }
    public Guid GuidC { get; set; }

public class TypeB
    public string StringX { get; set; }
    public int intY { get; set; }
    public string StringZ { get; set; }

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:

static void Main(string[] args)
    // set up a new container
    var container = new WindsorContainer();
    // register the service/components

    // instance of a mappable type
    TypeA typeA = new TypeA()
        StringA = "some string",
        IntB = 123,
        GuidC = Guid.NewGuid()

    // get the mapping provider and instantiate Mapper
    IMappingProvider provider = container.Resolve<IMappingProvider>();
    Mapper mapper = new Mapper(provider);
    // expect TypeB returned
    TypeB typeB = mapper.Map<TypeB>(typeA);


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.


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.


Initial submission.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Dave Sexton
Software Developer (Senior)
Ireland Ireland

Comments and Discussions

SuggestionWhy not just use Extension like this... Pin
Paw Jershauge11-Oct-13 0:50
memberPaw Jershauge11-Oct-13 0:50 
GeneralMy vote of 1 Pin
red baron23-Dec-10 18:55
memberred baron23-Dec-10 18:55 
GeneralRe: My vote of 1 Pin
Dave Sexton9-Jan-11 12:27
memberDave Sexton9-Jan-11 12:27 
GeneralMy vote of 3. Pin
James Curran19-Dec-10 16:02
memberJames Curran19-Dec-10 16:02 
GeneralRe: My vote of 3. Pin
Dave Sexton19-Dec-10 23:15
memberDave Sexton19-Dec-10 23:15 
GeneralNice idea shame there is already such a well established solution out there... [modified] Pin
Sacha Barber19-Dec-10 5:43
mvaSacha Barber19-Dec-10 5:43 
GeneralRe: Nice idea shame there is already such a well established solution out there... Pin
Dave Sexton19-Dec-10 7:10
memberDave Sexton19-Dec-10 7:10 
GeneralRe: Nice idea shame there is already such a well established solution out there... Pin
Sacha Barber19-Dec-10 7:24
mvaSacha Barber19-Dec-10 7:24 
GeneralRe: Nice idea shame there is already such a well established solution out there... Pin
Dave Sexton19-Dec-10 7:29
memberDave Sexton19-Dec-10 7:29 
GeneralMy vote of 5 Pin
Shahriar Iqbal Chowdhury/Galib18-Dec-10 19:27
professionalShahriar Iqbal Chowdhury/Galib18-Dec-10 19:27 
GeneralMy vote of 5 Pin
BigJim6118-Dec-10 11:47
memberBigJim6118-Dec-10 11:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Posted 18 Dec 2010


19 bookmarked