Generate mapping code with Roslyn code fix provider.
A few weeks ago I posted about negative aspects of applying AutoMapper. As an alternative I suggested typing all mapping code by hand or utilize some kind of generator like T4Scaffoling or something Roslyn based. In the past I experimented with T4Scaffoling but it was quite tedious. It requires preparation of templates in T4 syntax, referencing it to the project and writing some PowerShell code to provide data for templates. There also was an issue with assembly locking. Then I tried to generate code with PowerShell and EnvDTE. It worked but it had some limitations and it wasn’t convenient enough to start using it on a daily basis. I gave it one more try and after publication of mentioned post I started looking for an existing Roslyn-based solution that could be a really nice substitution for AutoMapper. That’s how I found ObjectMapper project.
At first it looked promising but after some analysis I found few things I didn’t like about it. For instance, it requires referencing additional library which contains attributes and interfaces used to mark mapping methods. In practice it means that I need to install additional nuget package to every project in which I want to use mapping generation feature which is quite uncomfortable. So I’ve tried to create my own version which will be distributed in the form of Visual Studio Extension and will use conventions to locate candidates for potential mapping methods. I was interested in generating implementation for the following kinds of methods:
-
Pure mapping method - non-void method that takes single parameter
public UserDTO Map(UserEntity entity) { throw new NotImplementedException(); }
-
Updating method - void method that takes two parameters
public void Update(UserDTO source, UserEntity target) { throw new NotImplementedException(); }
-
Mapping Constructor - constructor that takes single parameter
public UserDTO(UserEntity user) { }
-
Updating member method - void member method that takes single parameter
public void UpdateWith(UserEntity en) { throw new NotImplementedException(); }
Thanks to the abilities Roslyn gives, I could quite easily create code fix provider that generates implementation for the types of mapping methods mentioned above. A sample code generation in action looks as follows:
I’ve publish source code on github and if you are interested in testing it in action you can install it as Visual Studio Extension from Visual Studio Marketplace. For now it covers a few basic scenarios (you can read more about it on github) and there is a lot of things that could be improved such as:
- extracting method for mapping complex properties
- reusing existing mapping method to map complex properties
- using initialization block to create new objects
- updating collection instead of replacing content completely
- improving local variables names generating to avoid collisions
With a new asset in my developer toolbox now I’m able to quickly generate this boring mapping code and focus enirely on the real coding problems. There is also another positive side effect that comes from the convention-based mappings - it enforces the cohesion of naming. If you have different names for the same thing on both mapping sides you have more code to write manually ;)
UPDATE 2021-06-03: MappningGenerator project evaluated into a commercial product. You can get more info on the product landing page www.mappinggenerator.net