C#静态对象引用
c# static object reference
我有一个class像这样
public class FileLogger
{
public FileLogger(string typeOfLog)
{
//implementation
}
public void LogError(string err)
{
//implementation
}
public void LogMessage(string err)
{
//implementation
}
}
由于这是应用程序将其输出记录到文件的日志记录 class,因此人们会期望它是静态的 class。然而,如您所见,事实并非如此。然而,它在应用程序中是这样使用的:
public class BugetApplication
{
private static FileLogger logger;
//constructor
public BugetApplicationClass()
{
logger = new FileLogger("some-constructor-parameter");
}
//a method that uses the FileLogger class for logging
public string Classify()
{
try
{
//start multiple threads for classification
Classification clsf = new Classification();
clsf.handleEvent += clsf_handleEvent;
clsf.Classify();
}
catch (Exception exp)
{
logger.LogError(exp.Message);
}
}
private static void clsf_handleEvent(string errString)
{
if(errString.Contains("error"))
{
logger.LogError(errString);
}
}
}
多线程由 BugetApplication class 的 classify 方法启动。 class 中的任何错误都会触发在 BugetApplication class 的 clsf_handleEvent 方法中处理的事件。所以多个线程可以各自触发自己的事件。在 BugetApplication class 中将实例变量创建为静态变量是否会产生任何影响,或者将其保持为非静态是否具有相同的效果?我不希望任何一个线程覆盖另一个线程的错误消息。
编辑
只是为了清除问题,仅创建一次的 BugetApplication class 有一个静态变量 'static FileLogger logger; ' 它在其构造函数中创建了一个实例,将一些值传递给 FileLogger [=25 的构造函数=].在 BugetApplication class 中,有一个方法调用分类 class 的 classify 方法。 Classify 方法启动各种线程,并在出现任何错误时触发一个事件,该事件在 BugetApplication class 中处理,因此此 clsf_handleEvent 方法可以对其进行多次调用。
为什么您认为它会覆盖另一个线程的错误消息?记录器应该只附加消息,所以不应该有任何覆盖(虽然取决于你如何处理日志记录)。但是有一个潜在的问题 - 根据您的日志记录功能,您可能会阻止对该文件的访问。因为该方法适用于外部文件,所以您应该在函数中使用 lock
。
class 是否是静态的并不重要,问题是并发访问外部资源需要同步多线程才能成为线程安全的。
这真的取决于记录器的实际实现。
静态 classes 现在不受欢迎,因为它们使单元测试更加困难。许多传统上作为静态或单例实现的设施(记录器、电子邮件等)现在提供单元 test/IoC 友好的替代方案(例如工厂和接口或虚拟 class)。
这些设施的设计通常是客户端应用程序用来交互的前端 class 和负责同步和实际日志记录(或电子邮件,或其他)的异步后端。
关键在于前端是否多线程。
如果他们不是;你应该为每个线程创建一个新的。在这种情况下,记录器可能必须是局部变量或使用它的方法的参数。
然而,通常它们是多线程和可重入的,因为它们所做的只是将日志消息传递到后端并且没有自己的状态。在这种情况下,它们可以保存为静态变量或应用程序范围的单例,但最好在 IoC 容器中将它们实例化为单例并使用它们将其注入 classes。这样做可以使使用模拟记录器编写单元测试变得容易得多。
我有一个class像这样
public class FileLogger
{
public FileLogger(string typeOfLog)
{
//implementation
}
public void LogError(string err)
{
//implementation
}
public void LogMessage(string err)
{
//implementation
}
}
由于这是应用程序将其输出记录到文件的日志记录 class,因此人们会期望它是静态的 class。然而,如您所见,事实并非如此。然而,它在应用程序中是这样使用的:
public class BugetApplication
{
private static FileLogger logger;
//constructor
public BugetApplicationClass()
{
logger = new FileLogger("some-constructor-parameter");
}
//a method that uses the FileLogger class for logging
public string Classify()
{
try
{
//start multiple threads for classification
Classification clsf = new Classification();
clsf.handleEvent += clsf_handleEvent;
clsf.Classify();
}
catch (Exception exp)
{
logger.LogError(exp.Message);
}
}
private static void clsf_handleEvent(string errString)
{
if(errString.Contains("error"))
{
logger.LogError(errString);
}
}
}
多线程由 BugetApplication class 的 classify 方法启动。 class 中的任何错误都会触发在 BugetApplication class 的 clsf_handleEvent 方法中处理的事件。所以多个线程可以各自触发自己的事件。在 BugetApplication class 中将实例变量创建为静态变量是否会产生任何影响,或者将其保持为非静态是否具有相同的效果?我不希望任何一个线程覆盖另一个线程的错误消息。
编辑 只是为了清除问题,仅创建一次的 BugetApplication class 有一个静态变量 'static FileLogger logger; ' 它在其构造函数中创建了一个实例,将一些值传递给 FileLogger [=25 的构造函数=].在 BugetApplication class 中,有一个方法调用分类 class 的 classify 方法。 Classify 方法启动各种线程,并在出现任何错误时触发一个事件,该事件在 BugetApplication class 中处理,因此此 clsf_handleEvent 方法可以对其进行多次调用。
为什么您认为它会覆盖另一个线程的错误消息?记录器应该只附加消息,所以不应该有任何覆盖(虽然取决于你如何处理日志记录)。但是有一个潜在的问题 - 根据您的日志记录功能,您可能会阻止对该文件的访问。因为该方法适用于外部文件,所以您应该在函数中使用 lock
。
class 是否是静态的并不重要,问题是并发访问外部资源需要同步多线程才能成为线程安全的。
这真的取决于记录器的实际实现。 静态 classes 现在不受欢迎,因为它们使单元测试更加困难。许多传统上作为静态或单例实现的设施(记录器、电子邮件等)现在提供单元 test/IoC 友好的替代方案(例如工厂和接口或虚拟 class)。
这些设施的设计通常是客户端应用程序用来交互的前端 class 和负责同步和实际日志记录(或电子邮件,或其他)的异步后端。
关键在于前端是否多线程。
如果他们不是;你应该为每个线程创建一个新的。在这种情况下,记录器可能必须是局部变量或使用它的方法的参数。
然而,通常它们是多线程和可重入的,因为它们所做的只是将日志消息传递到后端并且没有自己的状态。在这种情况下,它们可以保存为静态变量或应用程序范围的单例,但最好在 IoC 容器中将它们实例化为单例并使用它们将其注入 classes。这样做可以使使用模拟记录器编写单元测试变得容易得多。