3

I'm trying to use AutoMapper to take data from a class that has prefixes before property names and map it to a second class that doesn't have those prefixes. However, I don't necessarily want it to always strip out that prefix: I just want it to do it for this particular mapping.

My source class looks like this:

public class AdvancedSearchFilterDataModel
{
    // ....

    public string ServiceMeterNumber { get; set; }

    // ....
}

My destination class looks like this:

[DataContract]
public class ServicesAdvancedSearchFilterData : AdvancedSearchFilterData
{
    // ....

    [DataMember]
    public string MeterNumber { get; set; }

    // ....
}

When I try to map values like this, it works:

Mapper.Configuration.RecognizePrefixes("Service");
Mapper.CreateMap<AdvancedSearchFilterDataModel, ServicesAdvancedSearchFilterData>();
ServicesAdvancedSearchFilterData servciesFilterData = 
    Mapper.Map<ServicesAdvancedSearchFilterData>(model);

But I only want "Service" to be recognized as a prefix for certain mappings, since it's also used as a normal part of property names in other mappings. I tried to handle this with a profile, but this didn't work -- no data was mapped:

Mapper.CreateProfile("ServicePrefix").RecognizePrefixes("Service");
Mapper.CreateMap<AdvancedSearchFilterDataModel, ServicesAdvancedSearchFilterData>()
    .WithProfile("ServicePrefix");
ServicesAdvancedSearchFilterData servciesFilterData = 
    Mapper.Map<ServicesAdvancedSearchFilterData>(model);

How can I make it recognize the prefix only when I want it to, either using profiles or some other technique? (I also have other prefixes that I'm going to need it to recognize for other mappings in the same way.)

JJS
  • 35
  • 6

1 Answers1

2

I achieved this functionality by creating following structure:

I have Person model for my view which is flattened from PersonCombined

public class PersonCombined
{
    public Person Person { get; set; }
    public Address DefaultAddress { get; set; }
    public Contact EmailContact { get; set; }
    public Contact PhoneContact { get; set; }
    public Contact WebsiteContact { get; set; }
}

public class Person : IWebServiceModel
{
    public int ID { get; set; }

    public string PersonFirstName { get; set; }
    public string PersonSurname { get; set; }
    public string PersonDescription { get; set; }
    public Nullable<bool> PersonIsActive { get; set; }
}

Then I have separate class for this mapping only that looks like this:

public class PersonCustomMapping : ICustomMapping
{
    const string separator = " ";

    private static IMappingEngine _MappingEngine;
    public IMappingEngine MappingEngine
    {
        get
        {
            if (_MappingEngine == null)
            {
                var configuration = new ConfigurationStore(new TypeMapFactory(), AutoMapper.Mappers.MapperRegistry.Mappers);
                configuration.RecognizePrefixes("Person");
                configuration.RecognizeDestinationPrefixes("Person");

                configuration.CreateMap<Person, MCIACRM.Model.Combine.PersonCombined>();
                configuration.CreateMap<MCIACRM.Model.Combine.PersonCombined, Person>();


                _MappingEngine = new MappingEngine(configuration);
            }

            return _MappingEngine;
        }
    }
}

In my generic view I have mappingEngine property like this:

    private IMappingEngine mappingEngine
    {
        get
        {
            if (_mappingEngine == null)
            {
                _mappingEngine = AutoMapper.Mapper.Engine;
            }

            return _mappingEngine;
        }
    }

Finally in my generic view constructor i have:

    public GenericEntityController(IGenericLogic<S> logic, ICustomMapping customMapping)
        : base()
    {
        this._mappingEngine = customMapping.MappingEngine;
        this.logic = logic;
    }

And that's how I do mapping: result = items.Project(mappingEngine).To<R>(); or logic.Update(mappingEngine.Map<S>(wsItem));

Because I use 1 entity per view I can define custom mapping configuration per entity. Hope this helps

BamboOS
  • 478
  • 5
  • 13
  • Thanks. I ended up implementing this in a different way, so I can't test this out and personally verify whether or not it works, but I'm going to tentatively mark it as "correct" anyway and hope that it's helpful for the next person who runs into this. – JJS Mar 21 '14 at 19:52
  • 5
    In my humble opinion, I find that this solution reach the f*** off point of complexity. I would do it manually. – Léon Pelletier May 14 '15 at 15:14
  • @JJS can you share your different way of implementing it? – xr280xr Aug 22 '17 at 18:21