2011-12-02 139 views
13

是否可以使用AutoMapper为私有setter分配属性?与私人setter的AutoMapper映射属性

+0

什么版本Automapper您使用的是?你尝试过吗? – PatrickSteele

+8

@blockhead实际上这是一个非常重要的问题,不可变对象比可以随意更改的对象(通过公开公开暴露他们的setter)更好。这是实体框架最近添加了水合到私有属性中的能力的确切原因,以允许域模型在初始水合之后保持不可变。也许这不是leozilla需要刷新他们的架构。 ;) – Marchy

+0

不好意思?私人财产应该是私人的。它是属于对象的数据,只有对象知道,应该知道这些数据。 – blockhead

回答

15

如果你在这样

public class RestrictedName 
{ 
    public RestrictedName(string name) 
    { 
     Name = name; 
    } 

    public string Name { get; private set; } 
} 

public class OpenName 
{ 
    public string Name { get; set; } 
} 

构造函数中设置该属性值,那么你可以使用ConstructUsing这样

Mapper.CreateMap<OpenName, RestrictedName>() 
      .ConstructUsing(s => new RestrictedName(s.Name)); 

,与此代码

var openName = new OpenName {Name = "a"}; 
var restrictedName = Mapper.Map<OpenName, RestrictedName>(openName); 
Assert.AreEqual(openName.Name, restrictedName.Name); 
+2

这似乎并不需要使用最新版本。我能够映射到私人设置者的班级。它必须在内部使用反射。 – Monstieur

+0

@Locutus也许你可以把这个评论变成一个答案?它应该被标记为这个问题的新答案。 – julealgon

9

工作AutoMapper现在允许(我不确定,因为何时)使用私人设置器映射属性。它使用反射来创建对象。

实例类:

public class Person 
{ 
    public string Name { get; set; } 
    public string Surname { get; set; } 
} 


public class PersonDto 
{ 
    public string Fullname { get; private set; } 
} 

和映射:

AutoMapper.Mapper.CreateMap<Person, PersonDto>() 
    .ForMember(dest => dest.Fullname, conf => conf.MapFrom(src => src.Name + " " + src.Surname)); 

var p = new Person() 
{ 
    Name = "John", 
    Surname = "Doe" 
}; 

var pDto = AutoMapper.Mapper.Map<PersonDto>(p); 

AutoMapper将映射属性与没有问题的私人二传手。如果你想强制封装,你需要使用IgnoreAllPropertiesWithAnInaccessibleSetter。使用此选项,所有私有属性(以及其他不可访问的)都将被忽略。

AutoMapper.Mapper.CreateMap<Person, PersonDto>() 
    .ForMember(dest => dest.Fullname, conf => conf.MapFrom(src => src.Name + " " + src.Surname)) 
    .IgnoreAllPropertiesWithAnInaccessibleSetter(); 

如果您使用Silverlight,问题就会浮现出来。根据MSDN:https://msdn.microsoft.com/en-us/library/stfy7tfc(v=VS.95).aspx

In Silverlight, you cannot use reflection to access private types and members. 
3

#600 Private/internal destination properties

解决方案:

public class PrivateInternalProfile { 
    protected override Configure() { 
     ShouldMapField = fieldInfo => true; 
     ShouldMapProperty = propertyInfo => true; 
     CreateMap<User, UserDto>(); //etc 
    } 
}