从Windows服务和ASP.NET中的DLL进行日志记录
我创建了一个.NET DLL,它是从Windows服务、Windows窗体和ASP.NET程序集引用的。DLL中包含相当多的日志记录到文本日志文件。从服务和winforms来看,这已经足够直截了当了,但显然不像通过ASP.NET写入日志文件那样直截了当从Windows服务和ASP.NET中的DLL进行日志记录,asp.net,.net,vb.net,Asp.net,.net,Vb.net,我创建了一个.NET DLL,它是从Windows服务、Windows窗体和ASP.NET程序集引用的。DLL中包含相当多的日志记录到文本日志文件。从服务和winforms来看,这已经足够直截了当了,但显然不像通过ASP.NET写入日志文件那样直截了当 有人能提供一些关于如何进行的建议吗?我想将日志代码保存在DLL中,从而在Windows服务和ASP.NET应用程序之间共享。这听起来不是个好主意。每当您试图创建在所有情况下都能神奇地工作的黑盒类型代码时,从长远来看,它总是导致无法管理的意大利面代
有人能提供一些关于如何进行的建议吗?我想将日志代码保存在DLL中,从而在Windows服务和ASP.NET应用程序之间共享。这听起来不是个好主意。每当您试图创建在所有情况下都能神奇地工作的黑盒类型代码时,从长远来看,它总是导致无法管理的意大利面代码。例如,如果有一天您决定需要两个windows服务,它们都使用相同的公共DLL,但其中一个需要记录到windows事件日志,另一个需要记录到文本文件,该怎么办。现在,让DLL自动确定它应该如何记录并不容易,代码变得更加混乱和复杂 依赖注入(DI)非常优雅地解决了这些问题。日志记录是一个单独的活动,因此应该由单独的日志记录程序类来处理。若日志记录是在它自己的类中处理的,那个么它将成为使用它的其他类的依赖项。类不应该隐藏它们的依赖关系,而应该要求将它们“注入”到它们中。有用于进行DI的工具和框架,但在构造函数中简单地请求依赖项也可以 要以DI方式执行,首先需要为记录器创建一个接口,例如:
Public Interface ILogger
Sub WriteEntry(message As String)
End Interface
Public Class MyBusiness
Public Sub New(logger As ILogger)
_logger = logger
End Sub
Private _logger As ILogger
Public Sub DoWork()
_logger.WriteEntry("Doing work")
End Sub
End Class
Dim fileWriter As IFileWriter = New MyFileWriter()
Dim logger As ILogger = New MyServiceLogger(fileWriter)
Dim dataAccess As IDataAccess = New MyDataAccess()
dim business As IBusiness = New MyBusiness(logger, dataAccess)
' Ta da!! I finally have a business object that I can now use
然后,在每个需要执行日志记录的类中,您将在构造函数中请求记录器,例如:
Public Interface ILogger
Sub WriteEntry(message As String)
End Interface
Public Class MyBusiness
Public Sub New(logger As ILogger)
_logger = logger
End Sub
Private _logger As ILogger
Public Sub DoWork()
_logger.WriteEntry("Doing work")
End Sub
End Class
Dim fileWriter As IFileWriter = New MyFileWriter()
Dim logger As ILogger = New MyServiceLogger(fileWriter)
Dim dataAccess As IDataAccess = New MyDataAccess()
dim business As IBusiness = New MyBusiness(logger, dataAccess)
' Ta da!! I finally have a business object that I can now use
正如您所看到的,现在您已经从业务类中完全删除了关于日志记录内部工作的任何知识,因此任何实现该接口的类都可以提供给它,并且它仍然可以工作。这样做很自由。现在,您可以在任何类型的项目中重用该业务类,而不管记录这些应用程序的要求是什么。您可以为它提供一个记录器,它可以写入文本文件、事件日志、数据库、屏幕和电子邮件,您可以为其命名——所有这些都不需要涉及使用它的业务类
现在,您可以轻松创建ILogger
接口的两个独立实现,一个用于服务,一个用于ASP.NET站点:
Public Class MyAspLogger
Implements ILogger
Public Sub WriteEntry(message As String) Implements ILogger.WriteEntry
' Do whatever an ASP project must do to log
End Sub
End Class
Public Class MyServiceLogger
Implements ILogger
Public Sub WriteEntry(message As String) Implements ILogger.WriteEntry
' Do whatever a service project must do to log
End Sub
End Class
然后,您可以从ASP项目中创建如下业务对象:
Dim business As New MyBusiness(New MyAspLogger())
Dim business As New MyBusiness(New MyServiceLogger())
从您的服务项目中,您可以这样创建它:
Dim business As New MyBusiness(New MyAspLogger())
Dim business As New MyBusiness(New MyServiceLogger())
理想情况下,您可以创建一个factory类来为您创建业务对象,这样您就不必每次需要创建MyBusiness
对象时都手动创建记录器(以及所有其他依赖项)
工厂没有具体的实现要求,它只是对类进行分类的一般术语。工厂类可以是唯一/主要目的是实例化其他类中的对象的任何类。在理想的情况下,使用DI,除了在工厂类中,您永远不会在代码中的任何地方使用New
关键字,但这并不总是实用的。一旦开始声明所有依赖项,就会发现实例化单个对象需要很多行代码,因为必须首先创建所有依赖项。例如:
Public Interface ILogger
Sub WriteEntry(message As String)
End Interface
Public Class MyBusiness
Public Sub New(logger As ILogger)
_logger = logger
End Sub
Private _logger As ILogger
Public Sub DoWork()
_logger.WriteEntry("Doing work")
End Sub
End Class
Dim fileWriter As IFileWriter = New MyFileWriter()
Dim logger As ILogger = New MyServiceLogger(fileWriter)
Dim dataAccess As IDataAccess = New MyDataAccess()
dim business As IBusiness = New MyBusiness(logger, dataAccess)
' Ta da!! I finally have a business object that I can now use
因此,如果您需要在同一个项目中的多个位置创建MyBusiness
对象,则需要大量复制的代码。如果不是出于方便的原因,设立工厂是有意义的,那么您可以这样做:
Dim factory As IBusinessFactory = New MyBusinessFactory()
Dim business As IBusiness = factory.NewMyBusiness()
然而,创建工厂类还有很多其他的好理由。例如,您可能需要在MyBusiness
内部按需创建多个记录器,因此在这种情况下,MyBusiness
不能简单地在其构造函数中请求单个ILogger
,而是可以请求实现NewLogger
方法的ILoggerFactory
。然后可以有两个独立的记录器工厂:一个根据请求返回新的MyAspLogger
对象,另一个创建新的MyServiceLogger
对象。这样,工厂本身就可以成为其他类的依赖项
工厂的另一个很好的理由是,你会发现实例化所有对象并以不同配置将它们连接在一起的代码本身就是一种特定的业务逻辑,应该以模块化的方式进行分离。这听起来是个坏主意。您真正应该做的是创建一个接口(例如,
ILogger
),然后在每个项目类型(ASP和服务)中为该接口分别进行具体实现。然后,让DLL中的适当类需要在构造函数中为它们提供一个ILogger
对象。这称为依赖注入。你可以在任何情况下重用相同的类,而不管日志记录可能需要如何完成。多加特先生+1,我的想法正是如此。例如,如果有一天您希望其中一个服务登录到文本文件,另一个服务登录到数据库或windows事件日志,但它们都使用相同的类库,该类库实现了自己的隐藏日志逻辑,该怎么办。突然你的代码变得复杂多了。嗯,有道理。到目前为止,我一直避免使用接口,因为我不完全理解它们。听起来是时候学习了。谢谢,史蒂文,谢谢。最后,接口开始有意义了。如果你不介意我再问几个问题的话。为了验证我是否正确:每次我实例化一个使用日志记录的类时,我都需要向它传递一个实现的类