1

Windows サービス、Windows フォーム、および ASP.NET アセンブリから参照される .NET DLL を作成しました。DLL には、テキスト ログ ファイルへの大量のログが含まれています。これは、サービスと winform からは簡単ですが、ASP.NET を介してログ ファイルに書き込もうとすると、明らかに簡単ではありません。

誰でもこれを行う方法についていくつかのヒントを提供できますか? ロギング コードを DLL に保持したいので、Windows サービスと ASP.NET アプリの間で共有されます。

4

1 に答える 1

3

それは悪い考えのように聞こえます。すべての状況で魔法のように機能するブラック ボックス タイプのコードを作成しようとすると、長期的には常に扱いにくいスパゲッティ コードになります。たとえば、ある日、同じ共通 DLL を使用する 2 つの Windows サービスが必要であると判断した場合、そのうちの 1 つは Windows イベント ログに記録する必要があり、もう 1 つはテキスト ファイルに記録する必要があるとします。現在、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

ご覧のとおり、ロギングの内部動作に関する知識をビジネス クラスから完全に削除したので、そのインターフェイスを実装する任意のクラスをビジネス クラスに与えることができ、それは引き続き機能します。このようにすることは、非常に自由です。アプリケーションのロギング要件に関係なく、あらゆるタイプのプロジェクトでそのビジネス クラスを再利用できるようになりました。テキスト ファイル、イベント ログ、データベース、画面、電子メールに書き込むロガーを与えることができます。名前を付けると、それを使用するビジネス クラスに一切手を加える必要がなくなります。

ILoggerこれで、インターフェイスの 2 つの個別の実装 (サービス用と 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())

理想的には、ビジネス オブジェクトを作成するファクトリ クラスを作成して、オブジェクトを作成する必要があるたびにロガー (および他のすべての依存関係) を手動で作成する必要がないようにしMyBusinessます。

ファクトリの特定の実装要件はありません。クラスを分類するための一般的な用語です。ファクトリ クラスは、他のクラスからオブジェクトをインスタンス化することを唯一/主な目的とするクラスです。DI を使用する理想的な世界ではNew、ファクトリ クラスを除いて、コード内のどこでもキーワードを使用することはありませんが、それが常に実用的であるとは限りません。すべての依存関係を宣言し始めると、最初にすべての依存関係を作成する必要があるため、1 つのオブジェクトをインスタンス化するのに何行ものコードが必要であることがわかります。例えば:

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単一のロガーを要求するだけではなく、メソッドを実装した を要求することができます。次に、2 つの別個のロガー ファクトリを作成できます。1 つは要求に応じて新しいオブジェクトを返し、もう 1 つは代わりに新しいオブジェクトを作成します。このようにして、ファクトリ自体が他のクラスの依存関係になることができます。ILoggerILoggerFactoryNewLoggerMyAspLoggerMyServiceLogger

ファクトリのもう 1 つの正当な理由は、すべてのオブジェクトをインスタンス化し、それらをさまざまな構成でまとめて接続するコードは、それ自体が、モジュール方式で分離するに値する特定の種類のビジネス ロジックであることがわかるからです。 .

于 2012-11-29T23:56:26.643 に答える