类设计:在线程安全性和可测试性方面,将数据文件封装成一个类
本文关键字:封装 文件 数据 一个 线程 可测试性 安全性 方面 | 更新日期: 2023-09-27 17:47:47
我正在用C#(.net 3.5)编写一个应用程序,我有一个关于类设计的问题:
我想创建一个访问文件(读、写)并将其内容提供给该类的用户(实例化器)的类。对实例最常见的操作是从文件中检索某个值。实际的读写(io)操作非常昂贵,所以我想将文件数据保存在内存中,并让所有实例访问这些数据。该类位于同时从各种应用程序使用的程序集中,所以我想我应该担心线程安全性。
我如何在线程安全性和单元可测试性方面进行设计(对于单元测试,必须使用与操作代码不同的输入文件)?非常感谢您的帮助。
首先,让您的类实现一个合适的接口。这样,客户就可以在根本不需要真实文件的情况下测试他们的行为。
测试线程安全性很难——我从来没有见过在这方面真正有用的东西,尽管这并不是说工具不存在。
对于单元测试您的类,如果可能的话,我建议它应该使用通用流而不仅仅是文件。然后,您可以在测试程序集中嵌入不同的测试文件,并使用GetManifestResourceStream引用它们。我过去已经做过好几次了,非常成功。
使用ReaderWriterLock,我认为它符合问题描述。
下面是一个快速而肮脏的实现。收购锁可能更明智,比如在救助前多次尝试。但你明白了:
public class MyFooBarClass
{
private static ReaderWriterLock readerWriterLock = new ReaderWriterLock();
private static MemoryStream fileMemoryStream;
// other instance members here
public void MyFooBarClass()
{
if(fileMemoryStream != null)
{
// probably expensive file read here
}
// initialize instance members here
}
public byte[] ReadBytes()
{
try
{
try
{
readerWriterLock.AcquireReaderLock(1000);
//... read bytes here
return bytesRead;
}
finally
{
readerWriterLock.ReleaseReaderLock();
}
}
catch(System.ApplicationException ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
public void WriteBytes(bytes[] bytesToWrite)
{
try
{
try
{
readerWriterLock.AcquireWriterLock(1000);
//... write bytes here
}
finally
{
readerWriterLock.ReleaseWriterLock();
}
}
catch(System.ApplicationException ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
}
关于线程安全:线程安全不是问题,除非单个应用程序中的多个线程将同时引用类的同一实例。除非您的类包含在进程外服务器中,否则多个应用程序无法同时引用同一实例。因此,您可能看到的冲突将来自文件共享冲突,而不是线程问题(换句话说,类的不同实例试图读取和写入同一文件)。是的,您必须设计适当的代码来处理文件共享。
使类单元可测试的一种方法是在构造函数中为类提供流,而不是让类直接访问文件。然后,单元测试可以提供内存流,而不是提供文件流。