これを実現する方法はいくつか考えられます。
固く結ばれた
リフレクションを使用して、DLL の存在を検出します。存在する場合は、適切なクラスをロードし、追加の呼び出しを行います。
これを行うには、Assembly.LoadFile、Assembly.GetType(string)、およびActivator.CreateInstance(type)を使用します。新しいインスタンスを抽象ベース ロガー タイプ/インターフェイスにキャストします。
これは多かれ少なかれあなたが説明していたことです。ただし、これはあまり柔軟ではなく、適切な代替手段があるため、お勧めしません。
疎結合
インターフェイスまたは抽象ロガー クラスを作成し、依存性注入 (制御の反転)を使用して、ロギングを行う必要があるコンポーネントにロガーを注入します。必要に応じて、依存性注入ライブラリを使用して、疎結合の方法で必要な実装を指定できます。追加の DLL (存在する場合) から依存関係を読み込むように DI ライブラリを構成します。
Castle.Windsor には疎結合のログ インターフェイス (ログ機能) があり、2 番目のオプションを調べることができます。
これらの間にも一種のスペクトルがあります。
これは、ロガーを依存関係として注入する要点です (ただし、この例ではライブラリを使用していません)。
using System;
using System.IO;
public interface ILogger
{
void WriteDebug(string debug);
void WriteInfo(string info);
void WriteError(string error);
}
public class NullLogger : ILogger
{
private static ILogger instance = new NullLogger();
// This singleton pattern is just here for convenience.
// We do this because pattern has you using null loggers constantly.
// If you use dependency injection elsewhere,
// try to avoid the temptation of implementing more singletons :)
public static ILogger Instance
{
get { return instance; }
}
public void WriteDebug(string debug) { }
public void WriteInfo(string info) { }
public void WriteError(string error) { }
}
public class FileLogger : ILogger, IDisposable
{
private StreamWriter fileWriter;
public FileLogger(string filename)
{
this.fileWriter = File.CreateText(filename);
}
public void Dispose()
{
if (fileWriter != null)
fileWriter.Dispose();
}
public void WriteDebug(string debug)
{
fileWriter.WriteLine("Debug - {0}", debug);
}
// WriteInfo, etc
}
public class SomeBusinessLogic
{
private ILogger logger = NullLogger.Instance;
public SomeBusinessLogic()
{
}
public void DoSomething()
{
logger.WriteInfo("some info to put in the log");
}
public ILogger Logger
{
get { return logger; }
set { logger = value; }
}
}
public class Program
{
static void Main(string[] args)
{
// You're free to use a dependency injection library for this,
// or simply check for a DLL via reflections and load a logger from there
using (var logger = new FileLogger("logfile.txt"))
{
var someBusinessLogic = new SomeBusinessLogic()
{
// The component won't know which logger it is using - it just uses it
Logger = logger,
};
someBusinessLogic.DoSomething();
}
}
}