Weaving with Fody – Creating A Lombok-Style RequiredArgsConstructor in .NET

By | November 21, 2015

Dargon’s codebase extensively leverages constructor-based dependency injection.

As a result, much of our codebase looks like this:

using ItzWarty.IO;
using System.IO;

namespace Dargon.Nest.Daemon.Hatchlings {
    public class NestDirectorySynchronizer {
      private readonly IFileSystemProxy fileSystemProxy;
      private readonly DaemonConfiguration daemonConfiguration;
      private readonly NestDirectoryImpl nestDirectory;
      private readonly NestContextFactory nestContextFactory;

      public NestDirectorySynchronizer(IFileSystemProxy fileSystemProxy, DaemonConfiguration daemonConfiguration, NestDirectoryImpl nestDirectory, NestContextFactory nestContextFactory) {
         this.fileSystemProxy = fileSystemProxy;
         this.daemonConfiguration = daemonConfiguration;
         this.nestDirectory = nestDirectory;
         this.nestContextFactory = nestContextFactory;
      }

Yuck, that’s six lines of boilerplate! I once worked on a team that leveraged a tool named Lombok which let you write Java code like….

import lombok.*;

package io.dargon.nest.daemon.hatchlings {
   @RequiredArgsConstructor
   public class NestDirectorySynchronizer {
      private final IFileSystemProxy fileSystemProxy;
      ...
      // no constructor!
   }
}

Nifty, eh? A year ago I started looking for this feature in C#. It didn’t seem to exist… but, over the last few hours, I built it! Those lines of code now look like:

using Fody.Constructors;
using ItzWarty.IO;
using System.IO;

namespace Dargon.Nest.Daemon.Hatchlings {
    [RequiredArgsConstructor]
    public class NestDirectorySynchronizer {
      private readonly IFileSystemProxy fileSystemProxy;
      private readonly DaemonConfiguration daemonConfiguration;
      private readonly NestDirectoryImpl nestDirectory;
      private readonly NestContextFactory nestContextFactory;

The code’s pushed to GitHub at ItzWarty/Constructors now. I’ll write a more in-depth post sometime soon, but the tl;dr is that I leveraged Fody and Mono.Cecil to add the constructors as a post-build process. The code is extremely simple, though it touches on basic CIL (.NET Bytecode) and requires understanding a bit about how C# code gets compiled – it’ll be a fun post!

I’ve also pushed Constructors.Fody to nuget.dargon.io, for those of you who wish to try it out :P

That’s all for now!

Michael.

Loading Facebook Comments ...

Leave a Reply

Your email address will not be published. Required fields are marked *