Skip to content

Constructor mapping does not work properly for abstract parameters #811

Description

Hello,

I have an issue with Mapster when using the MapToConstructor functionality.

If I have a ctor parameter that has an abstract type, and that parameter is null I get the following exception:

System.InvalidOperationException : Cannot instantiate type: AbstractDomainTestClass

I think Mapster should be able to handle null values in ctors for abstract types.

The following code showcases the issue:

using Mapster;
using MapsterMapper;
using NUnit.Framework;

public class MapsterCtorTests
{
    private Mapper _mapper;

    [SetUp]
    public void Setup()
    {
        _mapper = new Mapper();

        _mapper.Config.Default.MapToConstructor(true);

        _mapper.Config.NewConfig<AbstractDtoTestClass, AbstractDomainTestClass>()
            .Include<DerivedDtoTestClass, DerivedDomainTestClass>();
    }

    [Test(Description = "This works as expected")]
    public void Dto_To_Domain_MapsCorrectly()
    {
        var dtoDerived = new DerivedDtoTestClass
        {
            DerivedProperty = "DerivedValue",
            AbstractProperty = "AbstractValue"
        };

        var dto = new DtoTestClass
        {
            AbstractType = dtoDerived
        };

        var domain = dto.Adapt<DomainTestClass>();

        Assert.Multiple(() =>
        {
            Assert.That(domain.AbstractType, Is.Not.Null, "Abstract type not mapped correctly");
            Assert.That(domain.AbstractType, Is.TypeOf<DerivedDomainTestClass>(), "Abstract type not mapped correctly");

            var domainDerived = (DerivedDomainTestClass)domain.AbstractType;
            Assert.That(domainDerived.DerivedProperty, Is.EqualTo(dtoDerived.DerivedProperty), "Derived property not mapped correctly");
            Assert.That(domainDerived.AbstractProperty, Is.EqualTo(dtoDerived.AbstractProperty), "Abstract property not mapped correctly");
        });
    }

    [Test(Description = "This does not work, Mapster throws a InvalidOperationException with the following message: Cannot instantiate type: AbstractDomainTestClass")]
    public void Dto_To_Domain_AbstractClassNull_MapsCorrectly()
    {
        var dto = new DtoTestClass
        {
            AbstractType = null
        };

        var domain = dto.Adapt<DomainTestClass>();

        Assert.That(domain.AbstractType, Is.Null, "Abstract type not mapped correctly");
    }

    #region Immutable classes with private setters, map via ctors
    private abstract class AbstractDomainTestClass
    {
        public string AbstractProperty { get; private set; }

        protected AbstractDomainTestClass(string abstractProperty)
        {
            AbstractProperty = abstractProperty;
        }
    }

    private class DerivedDomainTestClass : AbstractDomainTestClass
    {
        public string DerivedProperty { get; private set; }

        /// <inheritdoc />
        public DerivedDomainTestClass(string abstractProperty, string derivedProperty)
            : base(abstractProperty)
        {
            DerivedProperty = derivedProperty;
        }
    }

    private class DomainTestClass
    {
        public AbstractDomainTestClass AbstractType { get; private set; }

        public DomainTestClass(
            AbstractDomainTestClass abstractType)
        {
            AbstractType = abstractType;
        }
    }
    #endregion

    #region DTO classes
    private abstract class AbstractDtoTestClass
    {
        public string AbstractProperty { get; set; }
    }

    private class DerivedDtoTestClass : AbstractDtoTestClass
    {
        public string DerivedProperty { get; set; }
    }

    private class DtoTestClass
    {
        public AbstractDtoTestClass AbstractType { get; set; }
    }
    #endregion
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions