Nservicebus: Deserialization private setters

Created on 27 Nov 2013  路  8Comments  路  Source: Particular/NServiceBus

It would be nice when you could set this setting on the DefaultContractResolver

defaultContractResolver.DefaultMembersSearchFlags |= BindingFlags.NonPublic

by default. So If the message has private setters you would be able to set them using the Json.

Most helpful comment

@SimonCropp
Here's are some arguments for enabling private setters:

Events
Events are by definition immutable since they represent something that has already happened.
As such having public setters on an event is conceptually wrong. Public setters imply that you are allowed to use them, but changing an event is completely forbidden.

Event Sourcing
Disabling the use of private setters destroys the safety features that immutability gives you, such as safe caching and multi-threaded use.
Without the assurance that the events it persists are immutable it is no longer safe to cache the events read from an event store.

Public API usage is fundamentally different from persistence and serialization mechanisms.
The public API of a class should be written so as to make it impossible to use it incorrectly.
A serialization mechanism is not a normal client of the API. It is a an infrastructure component that should be able to function correctly without forcing users of it to create misleading interfaces for their classes.

All 8 comments

why would you want private setters on a message?

An example is to have some Id's you would like to protect from change like the ProjectId. In this case the ProjectId will be created using constructor. Actually when NServiceBus deserializes the Message, the ProjectId is Null. So I created a private setter with the expectation the bus would behave like WebAPI. I was also looking for an extension which tells the bus to use the same serialization settings like WebAPI uses but have nothing found.

@marinkobabic

You realize the contradiction in this issue? You want to "protect" a property and you want NSB to bypass that protection using. So obviously anyone can use the same approach to bypass that protection. So what have you gained by "protecting properties"

Messages are DTOs and hence should be simple POCO classes with every property being writable.

If you have other models that are a similar shape to your messages you should consider something like AutoMapper https://github.com/AutoMapper/AutoMapper to convert between shapes

So I am closing this issue

You can manipulate every field using the reflection, is this a reason to not have private setters? The only idea is to protect ids from unintentional change. Json provides the feature but you are not giving an option to use it. Which pattern says that all the dto properties should have public setters? I don't think Udi would suggest to use AutoMapper.

@marinkobabic

given that a message is newed up and then sent when would someone have an opportunity to change the value?

while Json.net supports private fields other json serializers do not, so if NServiceBus ever decides to switch json serializers this would cause compatibility issues

there is a negative performance impact by using private setters since they must be set with reflection and cannot be optimized with runtime IL

you are free to create your serializer that supports private setters.

@SimonCropp
Here's are some arguments for enabling private setters:

Events
Events are by definition immutable since they represent something that has already happened.
As such having public setters on an event is conceptually wrong. Public setters imply that you are allowed to use them, but changing an event is completely forbidden.

Event Sourcing
Disabling the use of private setters destroys the safety features that immutability gives you, such as safe caching and multi-threaded use.
Without the assurance that the events it persists are immutable it is no longer safe to cache the events read from an event store.

Public API usage is fundamentally different from persistence and serialization mechanisms.
The public API of a class should be written so as to make it impossible to use it incorrectly.
A serialization mechanism is not a normal client of the API. It is a an infrastructure component that should be able to function correctly without forcing users of it to create misleading interfaces for their classes.

What was the outcome of this? Can the default JsonSerializer now set private properties?

@andreasohlund @danielmarbach

@frankclaassens I've modified https://docs.particular.net/samples/serializers/newtonsoft/ to use

public class CreateOrder :
   IMessage
{
   public CreateOrder(int orderId)
   {
       OrderId = orderId;
   }
   public int OrderId { get; private set; }
}

and that works all fine, is that what you're asking?

Was this page helpful?
0 / 5 - 0 ratings