基本的DI / IoC问题 - 架构,SimpleInjector

时间:2014-07-30 17:44:21

标签: c# .net asp.net-web-api dependency-injection simple-injector

在针对以下类型的体系结构设置IoC容器时,我有一个简单的挂断。

在我的应用程序中,我有这样的层(从下到上):

  • Project.Domain
  • Project.Web (System.Web.Http等加上一些核心HTTP类型逻辑)
    • 在这个项目中有一个 BaseController
  • Project.MicroServices 在Web API 2.2中实现GET / POST等。这些继承自Project.Web中的BaseController,并引用Project.Domain
  • Project.Logging 这是我尝试跨越日志记录

当请求MicroServices层中的控制器(GET,POST等)时,SimpleInjector使用属性注入将ILogger的实例添加到BaseController。因此,MicroServices项目中的任何控制器都可以访问它。到目前为止效果很好。

这是我的问题:

我希望即使在域层中也可以访问整个体系结构的日志记录,而不会破坏任何交叉规则并使事物分离。我的想法可能是从Logging层可以订阅的域层发布的事件。但是,我离题了。我不明白的是如何使SimpleInjector将Logger实例传递给域(如果我应该,想法?)它是在app启动时发生的,还是仅在Web请求上发生?它应该是单例实例还是瞬态实例?如何才能最好地适应Log4Net(可能我的架构过于复杂或不足之处)。

我意识到注册是在启动时发生的,但是如何获取实例呢?根据我的理解,我应该使用自动构造函数注入而不是使用Container.GetInstance()来获取实例,但是尽管我阅读了大量内容,但我仍然无法弄清楚它是如何在Web API请求和SimpleInjector&之外工作的。 #39; Web API Extensions。

另外,有点无关。我正在抽象出Log4Net功能,但我最近了解到我可能不应该这样做。如果考虑到这一点,我会喜欢一些关于这一切如何联系在一起的建议。

1 个答案:

答案 0 :(得分:4)

你的帖子有点含糊不清,而且没有更多的背景,这些问题很难回答,但我会尽我所能。

  

我甚至可以让整个架构都可以访问日志   在域层

如果您有明确的日志记录抽象,您可以将该抽象提供给应用程序并在整个应用程序中进行日志记录。

  

我正在抽象出Log4Net功能,但我最近学到了   我可能不应该这样做。

我不同意。我想你应该。如果可能,防止使应用程序的核心依赖于第三方组件,并且通过日志记录,这非常容易。符合define an abstraction原则的SOLID很容易。并且不要忘记,根据Dependency Inversion Principle,抽象应该是defined by the client。日志框架无法定义您需要的抽象。

但请确保不要像解释here那样陷入过多记录的陷阱。在大多数情况下,您不应该经常记录,而是快速失败,并且有一些通用的代码片段可以为您执行日志记录,而不是在整个代码库中调用您的ILogger.Log

如果您要发布事件,我认为这会大大降低您需要记录的时间,因为事件是完美的日志记录系统。只需将这些事件附加到表或磁盘上,您就会知道究竟在哪个时刻发生了什么。可能没有理由在日志中写入更多信息。

  

我不明白的是如何使SimpleInjector通过Logger   实例到域(如果我应该,想法?)

对此有很多意见。我和Mark Seemann赞成anemic domain models with commands and events on top(或者我可以说我的命令和事件会成为我的域模型吗?)。其他人在他们的域对象中有更多的业务逻辑。这些对象需要一些服务,例如ILoanCalculator,你可能想要依赖注入,因为让那些域对象通过服务位置请求服务是very bad idea

但不要忘记,不仅仅是构造函数注入。对于域对象,您可以使用方法注入,其中某些域方法需要的服务作为方法参数公开:

public class Loan
{
    public void PayLoan(LoanPeriod periodToPay, ILoanCalculator calculator)
    {
        // ...
    }
}

由于您将拥有调用这些域方法的服务类(我可以说command handlers吗?),您可以对这些服务类应用构造函数注入,并将依赖项传递给域方法。

  

我意识到注册是在启动时发生的,但是获取是怎么回事   实例

在每个请求开始时检索实例(构建对象图)。

  

据我所知,我应该使用自动构造函数注入   而不是使用Container.GetInstance()来获取实例

这是正确的。尽可能在从容器中解析的任何服务上使用构造函数注入。

  

但是尽管我阅读了很多,但我仍然无法弄明白   它在Web API请求和SimpleInjector的Web API之外工作   扩展。

我不确定我是否理解这一点。几乎所有应用程序都是基于请求的,无论是Web应用程序,Windows服务还是命令行工具。使用Web应用程序,请求作为Web请求从Internet进入。使用Windows服务,您有一个定时关闭的计时器,每个脉冲都可以看作是一个新请求(或者您可能正在使用SqlDependency,在这种情况下,引发的事件是新请求的开始)。控制台应用程序可能只有一个请求,然后很快就会死掉。对于Web应用程序,Simple Injector将隐式控制某些服务的生命周期,而Windows服务和后台进程则必须明确控制它。使用Simple Injector,LifetimeScopeExecutionContextScope生活方式允许您定义一个显式范围,该范围控制此类请求的对象的生命周期。 WebApiRequestLifestyle实际上在后台使用ExecutionContextScopeLifestyle,并根据Web API请求开始和结束范围。