mapperly icon indicating copy to clipboard operation
mapperly copied to clipboard

Allow something like "IgnorePrefix" on properties

Open pilotMike opened this issue 1 year ago • 9 comments

Is your feature request related to a problem? Please describe. I was trying to do a mapping and ran into an issue where I couldn't get the mapper to do it because the source and destination had slightly different prefixes.

Describe the solution you'd like Something like class IgnorePrefixAttribute(string SourcePrefix = null, string DestinationPrefix = null);

Describe alternatives you've considered I tried making intermediary types that would have a dot notation to match what I wanted, but the source generator couldn't work it out, ie Source: { FooBar } Destination: X { Y Foo }, Y { bool Bar }

pilotMike avatar Aug 02 '23 19:08 pilotMike

Hey, unfortunately Mapperly doesn't support automatic unflattening yet. Instead you can try using [MapProperty]

[Mapper]
public static partial class Mapper
{
    [MapProperty("FooBar", "Foo.Bar")]
    public static partial Destination Map(Source src);
}

TimothyMakkison avatar Aug 02 '23 19:08 TimothyMakkison

This may get implemented by https://github.com/riok/mapperly/pull/594

latonz avatar Aug 04 '23 15:08 latonz

Would it be worth adding regex support here? This way we don't have to add suffix and custom ignores as well.

[MapperIgnore("Local\w*")] // ignores all members starting with "Local"

TimothyMakkison avatar Dec 01 '23 16:12 TimothyMakkison

@TimothyMakkison I have mixed feelings about regex since it adds a lot of complexity on the users side for probably really rare use-cases.

latonz avatar Dec 02 '23 15:12 latonz

@latonz Adding support for more flexible member matching would be really useful. I have a DTO where I have A LOT of XyzInInputUnit properties that match to Xyz in the source object. Creating a [MapProperty] attribute for every one of them would be really tedious 😞.

AutoMapper has a feature to replace words and to recognize prefixes/suffixes. I think this is a quite common use case and the examples in their docs are quite practical.

InspiringCode avatar Apr 16 '24 08:04 InspiringCode

@InspiringCode this issue is about ignoring properties, so its related but not the same. I think as there are so many possible things on how users want to match properties Regex may really be the best option as @TimothyMakkison proposed. For the mapper ignore source/target attribute we could introduce a new property IsRegex. To match properties, a new related issue should be created. I think for this it could be implemented with new properties on the MapperAttribute with a match regex and the target regex replacement. For you sample this could look like this: (.+)InInputUnit => $1. The API would be a little more complex than a simple Prefix/suffix stripping but allows a lot more flexibility.

latonz avatar Apr 18 '24 18:04 latonz

@latonz Supporting regexes would be really valuable!

Regarding member name replacing, we have to consider multiple scenarios:

  1. Renaming target members,
  2. Renaming source members,
  3. Renaming muliple members,
  4. Explicitly mapping a member for which the expression would match.

Regarding point 1 and 2 my suggestion would be that the replacement is performed for both, the source and target property (similar to AutoMapper).

Regarding point 3, one way to implement this would be to make the Attribute-properties arrays:

[Mapper(ReplaceMemberNamesRegexes = ["(.+)InInputUnit", "Prsn" ], ReplaceMemberNamesWith=["$1", "Person"])]

Another approach would be to introduce a new ReplaceMemberNameAttribute that can be applied multiple times.

Regarding point 4: Ideally if one of the matched members is explicitly mapped, the explicit mapping should override the regex mapping like in the following example:

[Mapper(ReplaceMemberNameRegex="(.+)InInputUnit", ReplaceMemberNameWith="$1")]
public partial class WeatherMapper {
  [MapProperty(nameof(Weather.SpecialTemperature), nameof(WeatherDTO.SpecialTemperatureInInputUnit), Use=nameof(ConvertWithOffset))]
  public partial WeatherDTO Map(Weather source);
}

I would really love to see this feature in Mapperly. I have used it several times with AutoMapper and I am really missing it.

InspiringCode avatar Apr 23 '24 07:04 InspiringCode

You are describing even more advanced use-cases than I thought of.. This again increases the API complexity... 🤔 If I understand correctly, your approach would be for each property to walk through a list of regex and replace for each match. Instead of two lists I'd prefer two attributes which can be applied multiple times:

[MapperRenameProperty("(.+)InInputUnit", "$1")]
[MapperRenameProperty("Prsn", "Person")]
public partial class MyMapper;

Explicit MapProperty attributes should always take precedence. I'm still not really sure if we should increase the complexity that much.

@InspiringCode

I would really love to see this feature in Mapperly. I have used it several times with AutoMapper and I am really missing it.

You are referencing to ReplaceMemberName, RecognizePrefixes and the naming conventions of AutoMapper?

latonz avatar Apr 24 '24 03:04 latonz

@latonz Yes, that would be exactly my suggested approach. And yes, I was referring to ReplaceMemberName, RecognizePrefixes of AutoMapper.

InspiringCode avatar Apr 24 '24 09:04 InspiringCode