An Unexpected Journey — Updating Objects Partially in C#

Updating Objects Partially — The Right Way in C#Recently I had to update an object partially and in my naive mind I implement my own super-complicated solution, because I did not know enough about Patching. In this article I will take you on the journe…


This content originally appeared on Level Up Coding - Medium and was authored by Stefan Haas

Updating Objects Partially — The Right Way in C#

Recently I had to update an object partially and in my naive mind I implement my own super-complicated solution, because I did not know enough about Patching. In this article I will take you on the journey from a bloated unreliable solution to an excellent standardised way for patching.

UpdatePartial

It was obvious to me that updating objects partially is nothing unique to certain objects, but should be generic such that it could be reused for every object. That is why I chose to use Reflection — retrieving and setting property values of an object dynamically at runtime without hard-coding the properties. But because Reflection is known to be slow, I made a FastReflection Helper, which converts the GetMethod and SetMethod of a PropertyInfo into a delegate and then storing it into a static class variable. This means that the reflection is only slow on the first run and almost as fast as updating without reflection on the next runs because the delegates are cached.

Implementation

The interface shown below is used for retrieving the get/set delegates of a property. Note that a pattern matching switch is needed to specify the type because generic types must be hard-coded when a method call is invoked. This is also a big downside of this approach, because whenever the UpdatePartial method is implemented for some object, all of its property types must be in the pattern matching switch.

The static class Fast Reflection implements the UpdatePartial method and uses the IPropertyDelegateService to create a dictionary containing all the property updates.

A PropertyMode (Include, Exclude) is used to specify if the entries in the dictionary should be updated, or all properties of an object but those in the dictionary.

These are the foundations for the UpdatePartial method. To actually use it it is needed to create a concrete implementation of the IPropertyDelegateService. In principal all necessary methods are already implemented in the interface, but if the object that needs to be updated has special types, the pattern matching switch must be extended like below to also include the type (in this case CustomClass):

And now the only thing remaining is a class which stores the property delegates in a static variable. Because this all is very low level in terms of business concerns I created a CustomClassHelper which acts as a wrapper which hides the messy details.

Pros:

  • pretty generic
  • almost as fast as without using reflection

Cons:

  • custom types must be extended
  • nested objects cannot be partially updated
  • complicated

Although I felt very proud, that I got this monstrosity working at all, I soon came to the conclusion that effective and complicated code is not good, because my coworkers could not understand this solution without looking deep into it. It was is by far not self-explanatory, nor intuitive with the custom type pattern matching which must almost always be extended. After a few weeks I got a request for also updating the objects inside CustomClass partially and, to be honest, I did not have a clue how I could extend this thing to do that. I also did not want to touch it too much, because in the meanwhile I already forgot implementation details and I, myself, the creator of this had troubles wrapping my head around it.

Soon I figured I had to ditch it. It was just not maintainable at all and instead of investing too much time into adapting it a new solution had to be found. And this time it should be standardised. Something that I would not have to come up myself. And indeed I soon found the best solution ever.

JsonPatch

In REST the key difference between PUT and PATCH is that PUT makes an entire update on an object, meaning that an instance of an object is completely replaced by a new one. On the other hand Patch only specifies few properties of an object that should be updated/added/removed. This already sounds quite similar to the UpdatePartial I have implemented before, but with the difference that PATCH is a standardised methodology in the software engineering domain.

Whenever some partial update is done in a restful manner via json, the json string should look like this:

Operations:

  • Replace
  • Add
  • Remove
  • Copy
  • Move

The path specifies the property which should be updated. It is built similar to a file path, also having slashes with which properties of nested objects can be specified.

For instance you could use this path to replace the fourth element in a list like this:

Or you could go deep down nested objects and only update properties, without changing the entire nested objects, like this:

You see it is very simple to do complicated things with PATCH, but how do you construct those operations? To do it by your own would be tedious but luckily ASP.Net Core comes with a solution out-of-the-box.

JsonPatchDocument<T>

The JsonPatchDocument lets you build the operations very conveniently by calling the methods (Replace, Add, Remove, …) on itself and by passing an Expression<Func<CustomClass, TProp>> and the new value to each method. In the end you can simply use JsonConvert to serialize it to a json string which looks exactly like one of the images above. I wrote an extension method called Serialize which takes the old and the modified CustomClass as parameters and builds the JsonPatchDocument and returns the serialised object as a string because I had to send a restful patch request to a microservice. This microservice has a PATCH endpoint which receives JsonPatchDocument<CustomClass> which it uses to update an entity.

Compared to the UpdatePartial, this is way more simple because we do not have to worry about custom types and implement a helper service.

In order to actually then make a partial update, you can use the applyTo method which takes an object and applies all operations stored in a JsonPatchDocument to the object.

patch.applyTo(customClassInstance);

Pros:

  • simple
  • standardised
  • generic

Cons:

  • none

Conclusion

Through this journey I did not only learn that JsonPatch is awesome and should be used more frequently, but also that good code is simple and reliable.

From now on, whenever I feel like I am writing complicated code, I see a red flag and search for a simpler way. Most of the time the problem you or me are having is not unique and someone already might have found a solution and sometimes the community might even have agreed on such solutions to be standardised.


An Unexpected Journey — Updating Objects Partially in C# was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Stefan Haas


Print Share Comment Cite Upload Translate Updates
APA

Stefan Haas | Sciencx (2022-05-05T12:39:40+00:00) An Unexpected Journey — Updating Objects Partially in C#. Retrieved from https://www.scien.cx/2022/05/05/an-unexpected-journey-updating-objects-partially-in-c/

MLA
" » An Unexpected Journey — Updating Objects Partially in C#." Stefan Haas | Sciencx - Thursday May 5, 2022, https://www.scien.cx/2022/05/05/an-unexpected-journey-updating-objects-partially-in-c/
HARVARD
Stefan Haas | Sciencx Thursday May 5, 2022 » An Unexpected Journey — Updating Objects Partially in C#., viewed ,<https://www.scien.cx/2022/05/05/an-unexpected-journey-updating-objects-partially-in-c/>
VANCOUVER
Stefan Haas | Sciencx - » An Unexpected Journey — Updating Objects Partially in C#. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/05/05/an-unexpected-journey-updating-objects-partially-in-c/
CHICAGO
" » An Unexpected Journey — Updating Objects Partially in C#." Stefan Haas | Sciencx - Accessed . https://www.scien.cx/2022/05/05/an-unexpected-journey-updating-objects-partially-in-c/
IEEE
" » An Unexpected Journey — Updating Objects Partially in C#." Stefan Haas | Sciencx [Online]. Available: https://www.scien.cx/2022/05/05/an-unexpected-journey-updating-objects-partially-in-c/. [Accessed: ]
rf:citation
» An Unexpected Journey — Updating Objects Partially in C# | Stefan Haas | Sciencx | https://www.scien.cx/2022/05/05/an-unexpected-journey-updating-objects-partially-in-c/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.