Create Mappers
Writing your Mapper
A class mapper must implement the IMapper
interface from Mobilize.WebMap.Common.Messaging
. The first type parameter of this generic interface should be the model. The second parameter of the generic interface is the DTO class. For information on creating your mappers see the Creating a DTO.
This interface has three methods:
Map
this method is called to create a DTO instance and populate from the model. If you do not want to send anything to the client you can returnnull
ApplyChanges
this method is called tosync
back data from the client. In this method you can take data sent from the client and apply those changes to the model on the backend.Configure
this method is called to setup which data elements from the model must be considered as references.
A possible mapper for the previous DTO can be like the following code:
Mapper registration
Mappers need to be registered in a Registration class in order to be able to be accessed during the request/response execution. A mapper is specifically associated to a type, so, when each button in an application will always trigger the ButtonMapper to synchronize data.
Using the ObservableExtensions
You can also use using Mobilize.WebMAP.Common.Core
to include the ObservableExtensions
.
This will extensions add helper methods that can be used for several tasks.
NullableTypes
If you define properties like public int? Value
then the null value can be used when we know that those properties do not need to be sent.
For example with this code:
The extension method GetChanged
will return null
. Null values on the current formatting settings will not be sent.
Getting Events or Delegates
To get information about model delegates you can use several extensions methods.
For example to get information about all model delegates (regardless of whether they have been modified on the current request or not):
This will return a dictionary where each key is the Event or Delegate name and the value is a boolean value indicating if those events or delegates have a handler.
You can use restrict which events or delegates you need. For example:
You can also send only the events or delegates that changed during a request:
Sending private properties
Mappers and DTO should be created on a different assembly that the one where the model is defined. However, that makes it impossible to access private properties.
A recommendation is to make these properties internal
or expose them thru an internal
property. And then add a InternalsVisible('MappersAndDTOAssemblyName')
attribute to the models assembly. This will allow using this internals from the mappers.
Avoid setting properties with side effects
As a recommendation, if you have a property getter or setter that has some logic avoid using them directly and prefer to set other properties without any side effects.
Handling Calculated properties
Sometimes you cannot avoid using calculated properties. The problem with calculated properties is that the GetChanged
extension only works on properties with the Intercepted
attribute.
Let's see how to handle it on a hypothetical calculated property CalculatedProperty1
. Let's say that this property depends on PropertyA
and Reference.PropertyB
then in your mapper you can create a method like:
Creating Mappers with Factories
There are situations where you have types that are not completely known beforehand for example for generic types. In this case, you can create a factory class that will be used whenever a mapper is not found.
The mapper registration works only for a specific type, which, means that only if a control is of the same type that is registered it will be take part of the mapping process, although, in some cases it may be necessary to register different types to a particular mapper, in these cases WebMap provides a MapperFactory which is used to register several types to a Mapper. For example, if there is a GenericButton class that inherits from Button, by registering directly a Mapper it would only connect the Button type to it, but, if a MapperFactory is registered, both the Button and GenericButton class would go through the same mapper.
Let's say that you have a generic component Button
then the factory will be something like:
This factory will return a new ButtonMapper
instance using T
as InType and ButtonDataTransfer
as OutType
Last updated