1

注意:我也在AutoMapper 邮件列表上问过这个问题

我的 MVC 应用程序本质上具有两个级别的映射(针对此问题进行了简化):

RepositoryObject <-> Entity <-> ViewModel

我们创建了两个配置文件,每个配置文件处理适当映射级别的配置。

“RepositoryObjects”最终被序列化为 XML 并用于 REST Web 服务。我们发现的问题是 RepositoryObject 中的空集合会序列化为 XML 中的空元素,这会导致问题,因为 Web 服务要么不期望任何元素,要么期望包含数据的元素。

我们能够使用 AllowNullCollections 配置设置解决此问题。这将(当然)创建一个空集合而不是一个空集合,然后可以很好地序列化。

但是,我并不完全愿意将其作为全局设置,因为正如Jimmy 所指出的那样,它并不是真正的最佳实践。我很高兴将它包含在RepositoryObject <-> Entity映射中,因为 RepositoryObjects 是自动生成的(无论如何都很丑陋)并且它在应用程序中的级别非常低。但如果可能的话,我宁愿不要“破坏”Entity <-> ViewModel映射。

那么,是否可以为每个配置文件配置此设置?

谢谢。

更新

我在这里创建了测试代码:https ://gist.github.com/4069909

复制到这里供参考:

ProfileClasses.cs

namespace NullCollectionIssue
{
    using System.Collections.Generic;

    public class SourceProfileOne
    {
        public ICollection<string> Stuff { get; set; }
    }

    public class DestProfileOne
    {
        public ICollection<string> Stuff { get; set; }
    }

    public class SourceProfileTwo
    {
        public ICollection<string> Stuff { get; set; }
    }

    public class DestProfileTwo
    {
        public ICollection<string> Stuff { get; set; }
    }
}

AutoMapperConfigurator.cs

namespace NullCollectionIssue
{
    using AutoMapper;

    public class ProfileOne : Profile
    {
        public override string ProfileName
        {
            get
            {
                return "ProfileOne";
            }
        }

        protected override void Configure()
        {
            AllowNullCollections = true;
            Mapper.CreateMap<SourceProfileOne, DestProfileOne>();
        }
    }

    public class ProfileTwo : Profile
    {
        public override string ProfileName
        {
            get
            {
                return "ProfileTwo";
            }
        }

        protected override void Configure()
        {
            Mapper.CreateMap<SourceProfileTwo, DestProfileTwo>();
        }
    }

    public static class AutoMapperConfigurator
    {
        public static void Configure()
        {
            Mapper.Initialize(x =>
            {
                x.AddProfile<ProfileOne>();
                x.AddProfile<ProfileTwo>();
            });
        }
    }
}

映射测试.cs

namespace NullCollectionIssue
{
    using AutoMapper;

    using NUnit.Framework;

    [TestFixture]
    public class MappingTests
    {
        [Test]
        public void AutoMapper_Configuration_IsValid()
        {
            AutoMapperConfigurator.Configure();
            Mapper.AssertConfigurationIsValid();
        }

        [Test]
        public void AutoMapper_ProfileOne_AllowsNullCollections()
        {
            AutoMapperConfigurator.Configure();
            Mapper.AssertConfigurationIsValid();

            var source = new SourceProfileOne { Stuff = null };
            var dest = Mapper.Map<SourceProfileOne, DestProfileOne>(source);

            Assert.That(dest, Is.Not.Null);
            Assert.That(dest.Stuff, Is.Null);
        }

        [Test]
        public void AutoMapper_ProfileTwo_DoesntAllowNullCollections()
        {
            AutoMapperConfigurator.Configure();
            Mapper.AssertConfigurationIsValid();

            var source = new SourceProfileTwo { Stuff = null };
            var dest = Mapper.Map<SourceProfileTwo, DestProfileTwo>(source);

            Assert.That(dest, Is.Not.Null);
            Assert.That(dest.Stuff, Is.Not.Null);
            Assert.That(dest.Stuff, Is.Empty);
        }
    }
}

测试AutoMapper_Configuration_IsValidAutoMapper_ProfileTwo_DoesntAllowNullCollections通过,但测试AutoMapper_ProfileOne_AllowsNullCollections失败,因为dest.Stuff不为空。

4

2 回答 2

1

查看此功能的初始提交的源代码,这似乎是一个配置文件属性 - 查看 Profile.cs。

所以,我想,它应该适用于每个配置文件。我没有尝试过。

于 2012-11-10T13:35:38.067 回答
1

你得到这个行为是因为你Mapper.Map在你的 configure 方法中调用了静态:

protected override void Configure()
{
    Mapper.CreateMap<SourceProfileTwo, DestProfileTwo>();
}

应该改为

protected override void Configure()
{
    CreateMap<SourceProfileTwo, DestProfileTwo>();//leading Mapper. removed
}
于 2012-11-14T03:07:58.687 回答