我们使用 Automapper 一段时间了,我们认为它非常实用,感谢您创建它!
然而,我们有一个问题:
问题
“如何配置 AutoMapper 将源属性映射到内部目标属性?”
背景
在我们的分层架构中,Dto对象永远不会离开数据访问层,只有Domain对象被允许进出数据访问层。因此,从域 POV 来看,域对象不应包含任何数据库知识。然而,实际上数据库 ID 非常有用,随身携带 - 希望“业务层”开发人员不应该知道它们。
解决方案:将数据库 ID 添加到域对象,但将它们作为内部营销,这样它们就不会暴露给“业务层”。接下来将公共层(拥有域对象)内部结构公开给数据访问层。问题解决了。预计我们无法弄清楚如何让 Automapper (> v3.3.0) 使用我们的内部属性。
3.3.0版本BindingFlags被曝光,用于解决该问题。
例子
通用DLL
public class Person
{
   public Parent Father { get; set; }
   internal int FatherId {get; private set; }
}
数据访问.dll
internal class PersonDto
{
   public ParentDto Father { get; set; }
   public int FatherId {get; private set; }
}
在我们的 Profile 类中,我们有CreateMap<PersonDto, Person>();
编辑 1 - 修复了 Father 返回类型中的拼写错误。
编辑 2 - 添加更多信息..
在 Common.Dll 中,我们有类似这样的服务:
public class ParentService
{
    public Parent GetFather(Person person)
    {
        return repo.Parents.FirstOrDefault(parent => parent.Id = person.Father.Id);
    }
}
在 Business.Dll 中,我们让开发人员使用类似这样的服务:
var father = parentService.GetFather(son);
// use father separately or assign it to the son. Like so:
// son.Father = father;
重点是,我们不希望业务开发人员能够访问son.FatherIdBusinssess.Dll,也不希望他们能够访问创建域对象的 Dto 对象。
因此,所有“数据库”知识都封装在各种 Common.dll 服务或 DataAccess.dll 中。
谢谢。
这个问题在这里得到解答。
为了方便我引用一下答案:
只需在初始化方法中设置配置对象的 ShouldMapProperty 属性即可。
以下是使用静态 API 的示例,但是,您应该能够通过使用非静态 API 以类似的方式实现相同的目的。
Mapper.Initialize(i =>
{
    i.ShouldMapProperty = p => p.GetMethod.IsPublic || p.GetMethod.IsAssembly;
    i.CreateMap<Source, Target>();                
});