我在C#中使用Microsoft Office Automation模型。例如,在Excel中,Workbook对象具有一个名为Sheets的属性,其中包含一个可枚举的Worksheet集合。 我想要的是
interface IWorkbook { ISheets Worksheets { get; } ... }
然后是一个实现:
class WorkbookImpl {
private Excel.Workbook _workbook;
public WorkbookImpl(Excel.Workbook workbook)
{
_workbook = workbook;
}
public ISheets Worksheets {
get
{
// What goes here? something like
return _workbook.Worksheets; // but obviously the type is wrong
}
}
...
关键是我以后可以实现各种接口的模拟,以便对代码进行IoC单元测试。
你能否建议如何完成这项工作,或者我的方法是否完全错误。
答案 0 :(得分:1)
您似乎在Office Automation模型和代码之间有效地构建了适配器层。所以,要适应你已经拥有的东西:
class WorkbookAdapter : IWorkbookAdapter
{
private Excel.Workbook _workbook;
public WorkbookAdapter(Excel.Workbook workbook)
{
_workbook = workbook;
}
public IEnumerable<ISheetAdapter> Worksheets
{
get
{
return this._workbook.Sheets
.Select(sheet => new SheetAdapter(sheet))
.Cast<ISheetAdapter>();
}
}
}
..其中SheetAdapter
类似于:
class SheetAdapter : ISheetAdapter
{
private Excel.Sheet _sheet;
public SheetAdapter(Excel.Sheet sheet)
{
_sheet = sheet;
}
// Sheet properties, methods, etc.
}
如果有意义,您可以将SheetAdapters
缓存在列表中,以避免每次调用Select
getter时都进行Cast
和Worksheets
调用。
现在,当你进行模拟时,可以使用List<ISheetAdapter>
或类似的东西支持你的模拟,并避免模拟en枚举器。模拟枚举器或集合类型通常是代码气味,并导致各种困难。最好使用实际的集合类型。