Is it possible to assign properties with private setters using AutoMapper?
-
What version of Automapper are you using? Have you tried doing it? – PatrickSteele Dec 02 '11 at 12:42
-
11@blockhead actually it's a very important question, immutable objects are a much better architectural practice than objects which can be changed at will (by exposing their setters publicly). This is the exact reason Entity Framework recently added the ability to hydrate into private properties, to allow the domain model to stay immutable after the initial hydration. Perhaps it is not leozilla that needs to brush up on their architecture. ;) – Marchy Feb 29 '12 at 19:54
-
Excuse me? Private properties are supposed to be private. It's data that belongs to the object, and only the object knows, and should know about that data. – blockhead Mar 01 '12 at 07:34
-
12@blockhead The OP is not talking about private properties, he is talking about public/protected properties with private setters (set accessor). Big distinction. – Beyers May 30 '12 at 13:57
3 Answers
AutoMapper allows now (I am not sure, since when) to map properties with private setters. It is using reflection for creating objects.
Example classes:
public class Person
{
public string Name { get; set; }
public string Surname { get; set; }
}
public class PersonDto
{
public string Fullname { get; private set; }
}
And mapping:
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 will map property with private setter with no problem. If you want to force encapsulation, you need to use IgnoreAllPropertiesWithAnInaccessibleSetter. With this option, all private properties (and other inaccessible) will be ignored.
AutoMapper.Mapper.CreateMap<Person, PersonDto>()
.ForMember(dest => dest.Fullname, conf => conf.MapFrom(src => src.Name + " " + src.Surname))
.IgnoreAllPropertiesWithAnInaccessibleSetter();
The problem will emerge, if you will use Silverlight. According to 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.

- 53,428
- 11
- 128
- 150

- 960
- 11
- 10
-
3This is tricky. ReSharper says the `private set` can be removed. But when I do that, AutoMapper is no longer able to map the property. It does not give an error, it just leaves the private property set to its initial value! – comecme May 07 '18 at 14:47
-
2@comecme that is because the code generated without private set and with private set are different. There simply is no set method generated that Automapper can use with reflection to set the value with. Resharper cannot analyse those situations when code accesses properties through reflection. That is why Resharper suggest that the private set method can be removed. – Lejdholt May 22 '18 at 12:05
-
4I understood why this is happening. I merely wanted to point out that I think it's tricky that AutoMapper is able to use private properties, because tools like ReSharper (and I suppose other static code analyzers also) will think the setter can safely be removed. – comecme May 31 '18 at 14:06
-
1@comecme Likely sometime since these comments were made, JetBrains has created an annotation library that it can bring in automatically for you and you can decorate such properties with a `[UsedImplicitly]` attribute. That tells ReSharper that something is used indirectly, via reflection or some other framework behavior. – Logarr Aug 13 '22 at 01:48
If you set the value for this properties in the constructor like this
public class RestrictedName
{
public RestrictedName(string name)
{
Name = name;
}
public string Name { get; private set; }
}
public class OpenName
{
public string Name { get; set; }
}
then you can use ConstructUsing like this
Mapper.CreateMap<OpenName, RestrictedName>()
.ConstructUsing(s => new RestrictedName(s.Name));
which works with this code
var openName = new OpenName {Name = "a"};
var restrictedName = Mapper.Map<OpenName, RestrictedName>(openName);
Assert.AreEqual(openName.Name, restrictedName.Name);

- 2,352
- 19
- 21
-
4This doesn't seem to be required with the latest version. I am able to map into classes with private setters. It must be using reflection internally. – Monstieur Jun 04 '13 at 07:13
-
1@Locutus Maybe you could turn that comment into an answer? It should probably be marked as the new answer to this question. – julealgon Apr 10 '15 at 14:00
See #600 Private/internal destination properties.
Solution:
public class PrivateInternalProfile {
protected override Configure() {
ShouldMapField = fieldInfo => true;
ShouldMapProperty = propertyInfo => true;
CreateMap<User, UserDto>(); //etc
}
}

- 2,317
- 1
- 25
- 21