如何模拟Excel VSTO插件中的行?

我试图在一个新的Range行中放置一个模拟的Range (包含值的单元格)。 但是当我尝试从Range访问特定元素时,会抛出exception。

我已经尝试了一切,有没有人知道我在这里做错了什么?

例外

消息:测试方法xxx.MockUtilsTest.MockRowsTest抛出exception:Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:无法将带有[]的索引应用于类型为“Castle.Proxies.RangeProxy”的表达式

测试

 [TestMethod] public void MockRowsTest() { var row1 = MockUtils.MockCells("test_row_1", "test_row_1"); var row2 = MockUtils.MockCells("test_row_2", "test_row_2"); var range = MockUtils.MockRows(row1, row2); Assert.IsNotNull(range); Assert.AreEqual(2, range.Count); Assert.IsNotNull(range.Rows); Assert.AreEqual(2, range.Rows.Count); Assert.AreSame(row1, range.Rows[1].Cells[1]); // exception is thrown here Assert.AreSame(row2, range.Rows[2].Cells[1]); Assert.AreEqual("test_row_1", range.Rows[1].Cells[1].Value2); Assert.AreEqual("test_row_2", range.Rows[2].Cells[1].Value2); } 

MockUtils

 public static Range MockCellValue2(Object value) { var cell = new Moq.Mock(); cell.Setup(c => c.Value2).Returns(value); return cell.Object; } public static Range MockCells(params Object[] values) { var cells = new Moq.Mock(); for (int i = 0; i  c[i + 1, Moq.It.IsAny()]).Returns(cell); } var row = new Moq.Mock(); row.SetupGet(r => r.Cells).Returns(cells.Object); row.SetupGet(r => r.Count).Returns(values.Length); return row.Object; } public static Range MockRows(params Range[] rows) { var mergedRows = MergeRanges(rows); var range = new Moq.Mock(); range.SetupGet(r => r.Count).Returns(rows.Length); range.SetupGet(r => r.Rows).Returns(() => mergedRows); range.Setup(r => r.GetEnumerator()).Returns(rows.GetEnumerator()); return range.Object; } public static Range MergeRanges(params Range[] ranges) { var range = new Moq.Mock(); for (int i = 0; i  r[i + 1, Moq.It.IsAny()]).Returns(ranges[i]); } range.SetupGet(r => r.Count).Returns(ranges.Length); range.Setup(r => r.GetEnumerator()).Returns(ranges.GetEnumerator()); return range.Object; } 

Range的索引器返回一个动态对象,这是您的问题的根源。

在此处输入图像描述

Moq使用Castle Dynamic proxy生成假对象, Castle.Proxies.RangeProxy是您生成的类。 由于此对象不是COM对象,因此正在调用C#Runtime绑定程序的处理。 运行时绑定程序解析类型并查找索引器方法,但由于生成的类没有它,因此无法解析它。

解决问题的最简单方法是将索引器结果返回到严格的Range局部变量:

在此处输入图像描述

然后你的测试将失败,因为range.Rows[1]等于row1

所以将测试代码更改为:

 [TestMethod] public void MockRowsTest() { var row1 = MockUtils.MockCells("test_row_1", "test_row_1"); var row2 = MockUtils.MockCells("test_row_2", "test_row_2"); var range = MockUtils.MockRows(row1, row2); Assert.IsNotNull(range); Assert.AreEqual(2, range.Count); Assert.IsNotNull(range.Rows); Assert.AreEqual(2, range.Rows.Count); Range x = range.Rows[1]; Range y = range.Rows[2]; var xCell = x.Cells[1]; var yCell = y.Cells[1]; Assert.AreSame(row1, x); Assert.AreSame(row2, y); Assert.AreEqual("test_row_1", xCell.Value2); Assert.AreEqual("test_row_2", yCell.Value2); } 

上述UT将通过测试。 IMO你应该打破你的聚合调用“primefacesOPS(多线)和方法”不是因为它会通过测试,因为它会使你的代码成为一个调试友好的代码。(我把你的代码称为“第11条规则”)从编写本文开始,它将被读取至少10次…所以让编译器删除传递的局部变量并使它成为一个调试友好的代码..)。

在这里,您可以阅读简单而简短的解释,其中包含有关c#中动态工作方式的链接。

在这里,您可以阅读有关Castle Dynamic Proxy的更多信息。

BTW; 你也可以这样做:

 Range x = range.Rows[1].Cells; var str = x[1].Value2; 

收到价值