A principle from Computer Science followed by most developers in software projects is the Separation of Concerns design principle.
This principle typically involves attempting to break down a software application into distinct sections addresses a separate area of concern or buisness functionality.
In Software Engineering, this is often taking a step further and we attempt to break components down to conceptual models. Hence we have what is defined as Logical Data Models.
A logical Data Model is a model of a specific problem domain of particular database management product or storage technology. These usually include Relational tables, columns and object-oriented classes.
This can also be further abstracted to a Conceptual Data model , which is a high-level description of the business's informational needs. Typically including main concepts and main relationships between them.
In his book Domain Driven Design - Eric Evans , advocates the following design principle:
- Placing the projects primary focus on core domain and domain logic
- basing complex designs on a model of the domain
- Initiate creative collaborations between technical and domain experts
- Iteratively refine conceptual models that address particular domain problems
The result of in two different objects models being defined in a project.
The Entity Data Model (EDM) is a set of concepts that describe the structure of data, regardless of its stored form. The EDM borrows from the Entity-Relationship Model.
Typically in .net projects this is implemented using the Entity Framework, which is an Object Relational Mapper (ORM)
Objects from the business-specific area that represent something meaningful to the domain expert. Domain objects are mostly represented by entities and value objects.
A challenge for most software developers is managing the mapping between these often wildly different objects.
Fortunately, great tools like Automapper make this task infinitely easier . One of the issue I found with most projects on which I have worked on which utilise Automapper, is that they have enevitably decided to implement all the Mapping logic in one central file, which is often referenced in the
StartUp.cs and this file usually becomes a large file and very difficult to locate the actual mapping you may be interested in or even find a suitable place to insert a mapping logic.
A few years ago, I came across a strategy on a blog post some years back and have continued to evolve it.
In a nutshell the core concept is to store all the mapping logic a Domain object requires within the class. The benefits to this are that the class is infnitely easier to unit test and by simply opening the class you can in an instant see all the mapping logic that is related to it.
There is no longer the need the need to hunt down several files in order to identify and fix bugs which may have resulted due to a mapping error.
I have also taken the time to wrap the code explained below into a re-usable nuget package for you to download and use in your projects.
We've implemented this in a library we have called rather unimaginatively
We have 3 interfaces in this library
We also have a
MappingConfigurationFactory class which implements the Reflection logic
We simply add a reference to that project to the
Api project. We now have to add the implementation of that class to the
Create Domain Object
We can now create our Domain Object Classes. We will implement these in their own Class library project. For the most part they will be Plain Old CSharp Objects (POCO), however you will notice that they will implement at least one of the mapping interfaces we have defined.
Create a new class library project
dotnet new classlib --name Api.Domain
We now need to create an empty
Marker class which serves as an entry point to point for our reflector. We'll just rename the autogenerated
Api.Domain project we'll create a folder and name it
Bots we'll add new class and call it
Add a reference to
We are now ready to add the Attributes of the class and the mapping logic that is associated with this class.
Test it out
We have basically completed our mapping implementation so we should go ahead and test it.
I have added an additional controller to the project and called it
RefereController and added a simple Get Method.
If we now start the application
dotnet run and navigate to the URl
http://localhost:5000/api/referer/get we will see that our application now returns the our Domain objects.
We explored how to make use of Automapper and reflection within code to enable placing mapping logic with Domain Object classes.