我有一个用C#编写的Web API应用程序。我正在努力确保设计符合SOLID原则。因此我使用Unity将依赖项注入我的控制器。但是我希望将控制器执行的操作从控制器本身中取出,因此它们实际上只是在其他(通常是静态的)对象上调用方法。例如:
public class MyController : ApiController
{
private readonly ISomeCrossCuttingInterface _instance;
private readonly ILog _log;
public MyController(ISomeCrossCuttingInterface someInterface, ILog log)
{
_instance = someInterface;
_log = log;
}
[HttpPost]
[ActionName("MyAction")]
public RequestResponse MyAction(MyActionData actionData)
{
try
{
return MyActionUser(actionData);
}
catch (Exception ex)
{
_log.Error("MyAction error", ex);
}
return ...;
}
private RequestResponse MyActionUser(MyActionData actionData)
{
var responseObj = StaticClass.SomeMethod(_instance, actionData);
var responseObj2 = StaticClass2.SomeMethod(_instance, responseObj2);
return CreateMyActionResponse(responseObj2);
}
private RequestResponse CreateMyActionResponse(...)
{
...
}
}
我遇到的一些焦虑是用于执行工作的对象(例如上面的StaticClass和StaticClass2)是否应该实际注入。目前他们还没有。已注入的对象是与交叉切割问题相关的对象,例如日志记录或数据访问,或由多个控制器使用的对象。那么为什么我不注入执行工作的对象呢?我在想这些内部'对象仅用于执行与一个控制器相关的特定工作。也就是说,控制器功能基本上被分解为具有单一责任的对象,每个控制器都拥有它自己独特的对象集,这些对象可以完成控制器需要做的任何事情。不过这是一个糟糕的设计吗?是否应该注射所有物体?任何输入真的很感激。
答案 0 :(得分:5)
使用SOLID原则被广泛接受,它将使您的代码更易于维护,可测试和灵活。如果您使用其中一些原则,那么最好不要使用任何原则。
尝试思考如果你想以某种方式改变你的静态类会发生什么。您是否可以确信此更改不会破坏您的某个控制器?您可以为静态类进行单元测试,也可以为控制器进行单元测试,但是您需要进行集成测试以检查它们是否一起工作。如果您注入静态类,那么您可以轻松地进行单元测试以检查方法是否被调用,返回正确的结果等。
此外,你真的不希望你的控制器做这个逻辑,它应该是好的和精益的,所以把所有内容放入服务,让服务处理逻辑,调用存储库等。然后将服务注入到控制器。
答案 1 :(得分:4)
你唯一不应注入的是稳定的第三方库,你肯定知道这些库不会改变,也不需要Testability,Maintainability,Parallel Development,Extensibility或Late Binding。
如果StaticClass
实际上包含MyController
的逻辑,为什么不将其作为StaticClass
的一部分包含在内?否则,它必须在另一个层面(不同的关注点)做其他事情。
我相信你的架子上已经有了这个优秀的资源,但为了确保,我会在这里放一个链接: Dependency Injection in .NET(马克西曼)。
根据我自己的个人经验:如果你实际上是在制作一个小应用程序,只是为了它的乐趣,你可能会在它完成时扔掉它,只是玩得开心。在这里和那里使用依赖注入,编写一些单元测试以查看它的感觉并掌握它。你做不完美。
例如,您可以在Console和WPF / WinForms应用程序之间轻松切换吗?需要改变什么?您可以轻松地在两个应用程序之间交换模块吗?尝试编写不同的ILog
实现。也许你希望你的日志在你的控制台上,也许你想要它们在一些GUI,txt或xml文件中。更改代码有多容易?松散耦合的代码是整点,依赖注入模式在这里有所帮助。
答案 2 :(得分:1)
好。
您似乎认为您想要模拟您的存储库。以类似的方式,您可能还想为StaticClass注入其他行为。但如果行为是固定的,那么保持原样。
如果你把所有东西都注射掉,你会发现它导致代码臃肿。所以我的建议是不要使用控制反转来加入SOLID的原则,而是用它来覆盖实际的测试场景。