说我有很多这样的样板代码:
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);
}
}
有没有办法使用像PostSharp这样的东西来删除样板代码并使它看起来像这样:
class MyClass
{
[ConstructorParametersAreClassMembers]
public MyClass(
IDependencyA dependencyA,
IDependencyB dependencyB)
{
...
}
...
public void SomeMethod()
{
this.dependencyA.DoSomething(this.dependencyB);
}
}
这甚至可能吗?
除此之外:这实际上是它在F#中的默认工作方式。
答案 0 :(得分:3)
这是可能的,但不是一种非常有吸引力的方法。我理解痛苦。我觉得C#在这一点上有点冗长。在应用SOLID原则时,您会获得许多小型和专注的课程。由于它们很小,编写构造函数的开销变得更大。
但是,您可以创建一个为您生成构造函数的T4模板,而不是使用PostSharp等代码编织工具。有一个T4ConstructorGenerator NuGet包,可以为你的项目添加一个T4模板,为你生成一个构造函数。
使用此模板,可以使用以下类:
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
}
}
将获得以下构造函数:
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();
模板通过添加部分类来完成此操作,因此其他原始代码不会受到影响。模板只会在以下时间添加构造函数:
如果您的构造函数通常包含额外的初始化(实际上在执行依赖注入时应该很少),您可以在实际类中实现部分OnCreated
方法,如下所示:
partial void OnCreated()
{
// do logic here
}
答案 1 :(得分:0)
这只是一种方法中的防御性编程,PostSharp或其他AOP工具当然可以处理,但我看一下代码,这似乎是架构中出现其他问题的症状。
您使用的是Inversion of Control容器/依赖注入工具(如StructureMap,Ninject等)吗?如果是这样,那么它应该为您处理依赖关系,如果您忘记连接某些内容,它将抛出异常。因此,这减少了对所有防御性编程的需求,同时仍允许您在构造函数中放入其他初始化代码。