Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mapping from a null array doesn't overwrite not null array with empty array when AllowNullCollections is false #936

Closed
dougdanger opened this issue Oct 19, 2015 · 4 comments
Milestone

Comments

@dougdanger
Copy link

class TestClass
{
    public string[] ArrayOfItems { get; set; }
    public List<string> ListOfItem { get; set; }
}

void Main()
{
    var one = new TestClass
    {
        ArrayOfItems = new string[] { "Red Fish", "Blue Fish" },
        ListOfItem = new List<string> { "One Fish", "Two Fish" }
    };

    Mapper.Configuration.AllowNullCollections = false;
    Mapper.CreateMap<TestClass, TestClass>();

    Mapper.Map(new TestClass(), one);
}

The expectation is that when mapping from a new instance of TestClass that ArrayOfItems will be an empty collection like ListOfItems. In LinqPad one.Dump() produces the following result:

current_behavior

When Mapper.Configuration.AllowNullCollections equals true both collections are appropriately null.

@jbogard
Copy link
Member

jbogard commented Oct 20, 2015

I'm confused, you're mapping a type to itself?

@TylerCarlson1
Copy link
Member

Maybe it's AssignableArrayMapper accounts for AllowNullCollections while Collection mapper does not?

@dougdanger
Copy link
Author

@jbogard I'm doing something like this in a unit testing utility:

class TestClass
{
    public Guid? Id { get; set; }
    public string[] Statuses { get; set; }
    public bool IsActive { get; set; }
}

void Main()
{
    Mapper.CreateMap<TestClass, TestClass>();
    var testCases = new TestClass
        {
            Id = new Guid("0c89741d-cd38-44f5-8a20-19819a561c25"),
            Statuses = new string[] { "Accepted", "Committed" },
            IsActive = true
        };
    var testObject = new TestClass(); // This isn't the exact implementation, but in effect this object is being reused in the loop below.
    var properties = new List<PropertyInfo>(typeof(TestClass).GetProperties());

    foreach(var property in properties)
    {
        object idealValue = property.GetValue(testCases, null);
        Mapper.Map(new TestClass(), testObject);
        property.SetValue(testObject, idealValue);
        var result = QueryRepo(testObject);
        Assert.IsNotNull(result);

        object garbageValue = GetGarbageValueOfType(property.PropertyType); // this will return a value of the correct type (for Id it'll be a new Guid, for Statuses it'll be an array with a Guid.NewGuid().ToString() as its only item, and for any Boolean it'll be the inverse of what is set)
        property.SetValue(testObject, garbageValue);
        result = QueryRepo(testObject);
        Assert.IsNull(result);
    }
}

Internally QueryRepo is using testObject to add where clauses to an IQueryable<T> using a series of if statements that makes sure values are not null and collections have contents before adding the where clause. The result of QueryRepo is a known object that can be retrieved by all the properties defined in testCases. I'm interesting in testing each property individually with a known value that I should always be able to retrieve it by and a random value that I should never be able to retrieve it by.

Querying the repository by Id and Statuses for both asserts work fine. When the loop hits IsActive, the mapping of the new instance of TestClass to the existing instance still has the Statuses array with the garbage value in it. When the query is executed it has two properties it's trying to run when I expected the mapping to clear out the garbage value from Statuses.

My current work around is defining arrays as such:

class TestClass
{
    public Guid? Id { get; set; }
    public string[] Statuses { get; set; } = new string[0];
    public bool IsActive { get; set; }
}

@jbogard jbogard added this to the 4.2.0 milestone Oct 23, 2015
@lock
Copy link

lock bot commented May 7, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators May 7, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants