Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save andykuszyk/bb9df54d6ee0674dee29a6b246ad3ef7 to your computer and use it in GitHub Desktop.
Save andykuszyk/bb9df54d6ee0674dee29a6b246ad3ef7 to your computer and use it in GitHub Desktop.
Using AutoMapper to map complex classes with members that are hidden behind an interface

Using AutoMapper to map complex classes with members that are hidden behind an interface

Background

I recently wanted to use AutoMapper (a .NET library for mapping objects of one type to another) to map class containing many properties that were of a type that also needed to be mapped to another, similar type. To make matters worse, the type that I wanted to map to didn't just have properties of a custom type, but these types were actually interfaces with custom implementations.

For example, the type I wanted to map from looked something like this:

public class OriginalParent
{
  public OriginalChild ChildProperty { get; }
}

public class OriginalChild
{
  public string Value { get; }
}

And the type I wanted to map to looked something like this:

public interface INewParent
{
  INewChild ChildProperty { get; }
}

public class NewParent : INewParent
{
  public INewChild ChildProperty { get; }
}

public interface INewChild
{
  string Value { get; }
}

public class NewChild : INewChild
{
  public string Value { get; }
}

Complications

There were a few problems in doing this, mainly related to how I was using AutoMapper, but also relating to the setup of my new class. I needed to provide a set accessor to the members on my new classes and also provide a ChildProperty with a concrete type, rather than an interface.

Property Accessors

AutoMapper needs a property accessor in order to set values, even if its private. As such, I had to change all my property accessors to look like this:

public string Value { get; private set; }

Property types and interfaces

AutoMapper can map to an interface without throwing an exception, but it doesn't map the property values themselves, because it doesn't have a concrete type to instantiate. As such, I needed NewParent to implement INewParent whilst still providing a concrete type for the ChildProperty property. This is achieved by providing an explicit interface implementation for INewChild:

INewChild INewParent.ChildProperty { get { return ChildProperty; } }

public NewChild ChildProperty { get; private set; }

AutoMapper usage

After I had made these changes, my AutoMapper configuration looked like this:

MapperConfiguration mapperConfiguratin = new MapperConfiguration(c =>
{
  c.CreateMap<OldParent, NewParent>();
  c.CreateMap<OldChild, NewChild>();
});

OldParent oldParent = new OldParent();
NewParent newParent = mapperConfiguration.CreateMapper().Map<NewParent>(oldParent);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment