mapperly icon indicating copy to clipboard operation
mapperly copied to clipboard

Increased support for XML/WSDL generated model mappings

Open jcbExp opened this issue 1 year ago • 2 comments

Is your feature request related to a problem? Please describe. We are currently using Mapperly to map from models generated from an external service's large WSDL file using svcutil. These models are automatically generated with <field>Specified properties to indicate nullability for types such as int. This creates an extremely large number of Mapperly warnings for these properties, making it hard to see what properties are actually unmapped. In addition, it also requires additional user mappers to be made to avoid default values being taken from the model even if the property was not originally in the input.

Describe the solution you'd like Boolean mapper configuration indicating in some form that the generated mappers should check for these 'Specified' properties and use these in the generated mappers, as well as suppress warnings for these source properties.

Example:

public class Source
{
    public int MyProperty { get; set; }
    public bool MyPropertySpecified { get; set; }
}

public class Target
{
    public int? MyProperty { get; set; }
}

[Mapper(UseSpecifiedProperties = true)]
public partial class Mapper
{
    public partial Target Map(Source source);
}

Suggested generated code:

// <auto-generated />
#nullable enable
namespace MyNamespace
{
    public partial class Mapper
    {
        [global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "4.1.1.0")]
        public partial global::MyNamespace.Target Map(global::MyNamespace.Source source)
        {
            var target = new global::MyNamespace.Target();
            target.MyProperty = source.MyPropertySpecified ? target.MyProperty : null;
            return target;
        }
    }
}

Describe alternatives you've considered Ignoring the properties using [MapperIgnoreSource()] is an alternative I've considered for removing the warnings, and user mappings are also an option for ensuring we map to null if the field is not specified.

However, the models themselves are from an external service and may be updated, as well as being extremely large and containing a lot of these properties (> 1000). Individually ignoring or mapping the properties would create a large amount of messy code and would generally be good to avoid.

Editing the source models themselves also needs to be avoided, since the service is regularly updated to add new fields and we would need to regenerate the models everytime this happens.

Additional context When generating these models using svcutil, the generated models generally follow the same naming convention of <field>Specified, and this should be the same when mapping models from any XML/WSDL service. Thus, I believe it could be useful to other users in the future who may encounter the same problem.

jcbExp avatar Dec 12 '24 15:12 jcbExp

I can see your use case, however it is quite "niche". Supporting all these edge cases will make Mapperly more complex, so we will probably only implement this if more people request it. It may also be implemented in a more flexible way, so that also Protos Has<Field> could be supported.

latonz avatar Dec 13 '24 09:12 latonz

I was also thinking of creating a similar issue, but in the context of Protobuf with its Has properties.

It seems that to implement this, as @latonz mentioned, a more flexible approach should be used. In my understanding, it could be something like

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class UseValueProvidedPropertiesCheckAttribute(string? prefix = null, string? suffix = null): Attribute;

which could be used as

[UseValueProvidedPropertiesCheck(prefix = "Has")]
[UseValueProvidedPropertiesCheck(suffix = "Specified")]
public partial Model MapToModel(Dto dto);

TonEnfer avatar Dec 13 '24 09:12 TonEnfer