我可以想出几种方法来实现这一点。
紧密耦合
使用反射来检测 DLL 的存在。如果存在,则加载适当的类,并对它们进行额外调用。
为此,请使用Assembly.LoadFile、Assembly.GetType(string)和Activator.CreateInstance(type)。将新实例转换为您的抽象基本记录器类型/接口。
这或多或少是你所描述的。不过,我不建议这样做,因为它不是很灵活,而且有很好的替代方案。
松耦合
创建一个接口或者抽象的logger类,使用依赖注入(Inversion of Control)将logger注入到需要做日志的组件中。如果您选择,您可以使用依赖注入库以松散耦合的方式指定您想要的实现。配置 DI 库以从额外的 DLL(如果存在)加载依赖项。
Castle.Windsor 有一个松耦合的日志接口(日志工具),您可以查看第二个选项。
在这些之间也有一种光谱。
这是将记录器作为依赖项注入的要点(尽管在此示例中我没有使用任何库):
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();
}
}
}