Say I have a lot of boilerplate code like this:
class MyClass
{
private readonly IDependencyA dependencyA;
private readonly IDependencyB dependencyB;
public MyClass(
IDependencyA dependencyA,
IDependencyB dependencyB)
{
if(dependencyA == null) throw ArgumentNullException("dependencyA");
if(dependencyB == null) throw ArgumentNullException("dependencyB");
this.dependencyA = dependencyA;
this.dependencyB = dependencyB;
...
}
...
public void SomeMethod()
{
this.dependencyA.DoSomething(this.dependencyB);
}
}
Is there a way to use something like PostSharp to remove the boilerplate code and make it look like this:
class MyClass
{
[ConstructorParametersAreClassMembers]
public MyClass(
IDependencyA dependencyA,
IDependencyB dependencyB)
{
...
}
...
public void SomeMethod()
{
this.dependencyA.DoSomething(this.dependencyB);
}
}
Is that even possible?
Aside: this is actually the way it works by default in F#.
This is possible, but not a very attractive method. I understand the pain. I find C# at this point a little to verbose. When applying the SOLID principles you get many small and focused classes. Since they are small, the overhead of writing constructors gets bigger.
But instead of using a code weaving tool such as PostSharp, you can also create a T4 template that generates the constructor for you. There is a T4ConstructorGenerator NuGet package that adds a T4 template to your project, which generates a constructor for you.
With this template the following class:
public class SomeService
{
private readonly ITimeProvider timeProvider;
private readonly ILogger logger;
private readonly IOrderCalculator calculator;
private readonly IMailSender mailSender;
public void SomeMethod()
{
// using the dependencies
}
}
Will get the following constructor:
public SomeService(
ITimeProvider timeProvider,
ILogger logger,
IOrderCalculator calculator,
IMailSender mailSender)
{
if (timeProvider == null) throw new ArgumentNullException("timeProvider");
if (logger == null) throw new ArgumentNullException("logger");
if (calculator == null) throw new ArgumentNullException("calculator");
if (mailSender == null) throw new ArgumentNullException("mailSender");
this.timeProvider = timeProvider;
this.logger = logger;
this.calculator = calculator;
this.mailSender = mailSender;
this.OnCreated();
}
partial void OnCreated();
The template does this by adding a partial class, so the rest original code will not be affected. The template will only add a constructor when:
In the case where your constructors often contain extra initialization (which in fact should be rare when doing Dependency Injection), you can simply implement the partial OnCreated
method in the real class, as follows:
partial void OnCreated()
{
// do logic here
}