tags:

views:

52

answers:

1

In the project I'm working on, we are mapping auto-generated DTOs to business objects. The database has an ahem unusual (but largely consistent) naming convention, which means that it's possible to transform most DTO property names to their equivalent business object property names, thus saving many lines of code.

For example, in the DTO (and database) we have a property called account_ID__created that will map to a BO property called CreatedAccountId. This is the kind of transformation happening in MemberNameTransformer.GetBoMemberName(), so it's not as simple as a slightly different convention with a different separator.

Following what I have available in the AutoMapper source code, I have this as my best guess:

public class DtoBoMappingOptions : IMappingOptions
{
    public INamingConvention SourceMemberNamingConvention
    {
        get { return new PascalCaseNamingConvention(); }
        set { throw new NotImplementedException(); }
    }

    public INamingConvention DestinationMemberNamingConvention
    {
        get { return new PascalCaseNamingConvention(); }
        set { throw new NotImplementedException(); }
    }

    public Func<string, string> SourceMemberNameTransformer
    {
        get { return s => s; }
        set { throw new NotImplementedException(); }
    }

    public Func<string, string> DestinationMemberNameTransformer
    {
        get { return MemberNameTransformer.GetBoMemberName; }
        set { throw new NotImplementedException(); }
    }
}

Now, how do I tell the Mapper to use these options when mapping SomeDto to SomeBusinessClass? I realize I may have the wrong interface in IMappingOptions. The real meat of what I'm trying to accomplish is in MemeberNameTransformer.GetBoMemberName().

Extra credit: How do I tell the Mapper to use these options when mapping any IDto to IBusinessObject?

+1  A: 

If things are really consistent, like textFirstName, you can use some built in functions.

Mapper.Initialize(cfg => cfg.RecognizePrefixes(new[] { "text" }));

Otherwise, you'll need to write your own INamingConvention class that looks something like this..

class DTONaming : INamingConvention
{

    #region INamingConvention Members

    public string SeparatorCharacter
    {
        get { return string.Empty; }
    }

    public Regex SplittingExpression
    {
        get { return new Regex(""); }
    }

    #endregion
}

Then you can register that with automapper.

Mapper.Initialize(cfg => cfg.SourceMemberNamingConvention = new DTONaming());

And AutoMapper will use this for any mappings, so if you need to restrict the registration of these prefixes or custom naming objects you may need to initialize and re-initialize it or something. I doubt the naming scheme would have consequences though.

Edit

With your recent additions you will be using a SourceMemberNameTransformer instead. This allows you to write a function that converts the names yourself.

Mapper.Initialize(cfg => cfg.SourceMemberNameTransformer = ConvertNames);
private static string ConvertNames(string inputString)
{
    var sections = inputString.Split('_');
    // transform the sections into w/e you need
    return inputString;
}
Jab
I don't think this will work for what I need. I've updated the question to reflect what exactly the naming convention is that I'm working with. I really need my Func<string, string> to say what destination member comes from what source member.
Josh Kodroff
@Josh Kodroff check the updated answer, I think that will be what you need.
Jab
That's it! I just couldn't figure out where to set the SourceMemberNameTransformer. Now, I am using the Mapper in multiple layers (DTO, BO, VM), so I don't want to use that transformer universally. Any ideas on how to make sure that doesn't happen?
Josh Kodroff