我有一个名为 ILogger 的接口,它基本上包含一些日志记录方法。
ilogger.cs
public interface ILogger
{
void LogError(string message, Exception exception = null);
void LogMessage(string message);
void LogValidationError(UploadResult uploadResult);
void LogValidationError(ValidationResult validationResult);
void LogProcessingError(string processingError);
}
我有一个实现这个接口的 LogHelper 类。LogHelper 类通过 StructureMap 进行实例化,例如
ObjectFactory.Initialize(
request =>
{
request.For<ILogger>().Singleton().Use<LogHelper>();
});
我有很多类在它们的构造函数中我只是实例化这个类并调用方法来记录信息。例如:我有一个类说 Dummy1 在其构造函数中我将 LogHelper 实例化为:
public Dummy1()
{
this.logger = ObjectFactory.GetInstance<ILogger>();
}
在 LogHelper 中,我有一个方法,它基本上创建日志文件并将作为参数传递给它的消息写入。
public void LogMessage(string message)
{
using (var writer = this.GetTextWriter(this.messageFilename))
{
writer.WriteLine(message);
}
}
目前,文件名被硬编码到 LogHelper 类的常量属性中private string messageFilename = "logs\\UserCreationResult.log"
;
但是我希望在实例化 LogHelper 时动态发送文件名。我想拥有一个类属性并在实例化类时在构造函数中定义该属性。但是由于 LogHelper 类被实例化为ObjectFactory.GetInstance<ILogger>()
. 我无法调用可以传递文件名的构造函数。
不幸的是,你这样做的方式有点弄巧成拙。你的类只知道ILogger
,没有任何特定的实现ILogger
。这很好 - 这意味着实现可以写入文件、SQL 表或任何内容。
但是如果你的类只知道ILogger
,而不知道实现,那么你的类怎么知道记录器需要一个文件路径?如果您将方法签名更改ILogger
为包含文件路径,则会发生两件事。
ILogger
是不写入一个文件(除非它忽略文件路径,这将是很奇怪的。)相反,在哪里以及如何记录的细节应该存在于你的ILogger
实现中。这更接近单一职责原则。调用的类ILogger
不负责有关如何ILogger
工作的决定。它不知道,也不想知道。上面写着“来,拿这个并记录下来。” 记录器实现负责其余的工作。
我建议ObjectFactory
完全取消静态并使用容器来解析和创建您的所有类,包括记录器和依赖于它的类,但这太广泛了,并没有真正的帮助。(它已被弃用,因为它是一个糟糕的模式。它甚至不在 StructureMap 的最新版本中。)
以上都是推荐。在此之后,我提供了一个不是真正值得推荐的选项,但需要较少的更改并使您的类不知道文件路径,因为请永远不要这样做。
一种选择 - 半途而废 - 可能是注册ILogger
. 您可以将记录器类修改为如下所示:
public class FileLogger : ILogger
{
private readonly string _filePath;
public FileLogger(string filePath)
{
_filePath = filePath;
}
}
现在您可以创建该记录器类的多个实例,向每个实例传递不同的文件路径。这样它就不是静态属性,它限制您只有一个文件路径。
然后你可以像这样注册你的实现。
ObjectFactory.Initialize(
request =>
{
request.For<ILogger>().Singleton()
.Use<FileLogger>(() => new FileLogger("some path")).Name = "LoggerOne";
request.For<ILogger>().Singleton()
.Use<FileLogger>(() => new FileLogger("some other path")).Name = "LoggerTwo";
});
现在,你的类可以说这就是了记录器,就像这样:
var logger = ObjectFactory.GetNamedInstance<ILogger>("LoggerOne");
但请不要真的那样做。这比我在这里可以详细描述的要多,但是看看依赖注入,这样你的类真的只知道ILogger
,不知道或不关心他们得到的实现,而不告诉它任何关于如何做它的实现工作。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句