0

I'm using AutoMapper v6.1.1 to map from my rich domain model entities to some flattened DTOs.

I'm initialising the configuration in a static class that returns an IMapper, which adds our mapping profiles and configures PreserveReferences() for all our maps.

I have declared a custom attribute against a subset of my source entity members (that only applies to members of type string).

I would like to add a global configuration to AutoMapper that allows me to call an extension method against any members with that attribute during the mapping.

Each of these members will end up in many different destination types, so I thought it would be a simple way of ensuring the extension method is always run for those members without explicitly configuring it for each new map.

A contrived example follows.

Source entity:

public class SomeEntity
{
    public string PropertyWithoutCustomAttribute { get; set; }

    [CustomAttribute]
    public string PropertyWithCustomAttribute { get; set; }
}

Target entity:

public class SomeEntityDto
{
    public string PropertyWithoutCustomAttribute { get; set; }

    public string PropertyWithCustomAttribute { get; set; }
}

Extension method:

public static string AppendExclamationMark(this string source)
{
    return source + "!";
}

If my source instance is defined with these values:

var source = new SomeEntity
{
    PropertyWithoutCustomAttribute = "Hello",
    PropertyWithCustomAttribute = "Goodbye"
};

I would expect the following statements to be true:

destination.PropertyWithoutCustomAttribute == "Hello"
destination.PropertyWithCustomAttribute == "Goodbye!"

I have become completely bogged down (and am struggling with the documentation somewhat) but I think the closest I have got is this:

cfg.ForAllPropertyMaps(
    map => map.SourceType == typeof(string) &&
           map.SourceMember
               .GetCustomAttributes(
                   typeof(CustomAttribute),
                   true)
               .Any(),
    (map, configuration) => map.???);

Any help would be greatly appreciated, even if to tell me it's a terrible idea or it's not possible.

Collin Barrett
  • 2,441
  • 5
  • 32
  • 53
Sir Crispalot
  • 4,792
  • 1
  • 39
  • 64
  • It's possible, but it's more difficult. Try to stick with the higher level features. Maybe [this](http://docs.automapper.org/en/latest/Value-transformers.html). – Lucian Bargaoanu Oct 24 '18 at 04:52
  • @LucianBargaoanu Thanks, but it doesn't look like that would allow me to apply the transformation *conditionally* depending on an attribute of the source property. I don't want to apply this to all strings. – Sir Crispalot Oct 24 '18 at 07:23
  • I would forget about the attribute. But if you must have that, then you need ForAllPropertyMaps. I was suggesting an easier solution. – Lucian Bargaoanu Oct 24 '18 at 07:40
  • The idea behind the attribute is that I can decorate some of the properties in the source model and guarantee that they'll have the extension method run against them without having to specify each time I create a new destination type and map. My example is simplified, but the source entity with the candidate members is actually mapped to many different destination types. Edited my question to explain. – Sir Crispalot Oct 24 '18 at 07:48
  • I see. Usually there an inheritance relation between those types and you would use Include/IncludeBase to reuse the configuration. But maybe in this particular case ForAllPropertyMaps fits better. ForAllMaps might work too. You can use that to conditionally apply a value transformer or a value resolver. You can look for examples in the AM repo and in the wild. – Lucian Bargaoanu Oct 24 '18 at 08:50

0 Answers0