programing

Excel VSTO 플러그인에서 행을 조롱하는 방법?

newstyles 2023. 10. 26. 20:48

Excel VSTO 플러그인에서 행을 조롱하는 방법?

나는 조롱을 당하려고 합니다.Range(값이 있는 셀 포함) 새 행 안에Range. 하지만 내가 특정 요소에 접근하려고 할 때Range, 예외가 인정됩니다.

다 해봤는데, 여기서 내가 뭘 잘못하고 있는지 아는 사람?

예외.

메시지:테스트 방법 xxx.모의유틸리티 테스트.MockRowsTest가 예외를 던졌습니다.마이크로소프트.씨샤프.런타임 바인더.RuntimeBinderException: []을(를) 사용하여 '캐슬' 유형의 식을 인덱싱할 수 없습니다.대리인.Range Proxy'

시험

[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);
}

모크유틸스

public static Range MockCellValue2(Object value)
{
    var cell = new Moq.Mock<Range>();
    cell.Setup(c => c.Value2).Returns(value);

    return cell.Object;
}

public static Range MockCells(params Object[] values)
{
    var cells = new Moq.Mock<Range>();
    for (int i = 0; i < values.Length; i++)
    {
        var cell = MockCellValue2(values[i]);
        cells.SetupGet(c => c[i + 1, Moq.It.IsAny<Object>()]).Returns(cell);
    }

    var row = new Moq.Mock<Range>();
    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>();
    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<Range>();
    for (int i = 0; i < ranges.Length; i++)
    {
        range.SetupGet(r => r[i + 1, Moq.It.IsAny<Object>()]).Returns(ranges[i]);
    }

    range.SetupGet(r => r.Count).Returns(ranges.Length);
    range.Setup(r => r.GetEnumerator()).Returns(ranges.GetEnumerator());

    return range.Object;
}

색인 작성자Range동적 개체를 반환합니다. 이것이 문제의 원인입니다.

enter image description here

머큐즈Castle Dynamic proxy가짜 물건을 만들기 위해,Castle.Proxies.RangeProxy당신의 경우에 생성된 클래스입니다.이 객체는 a가 아니기 때문에COM개체 C# Runtime 바인더가 호출되는 작업을 처리합니다.런타임 바인더는 유형을 확인하고 인덱서 메서드를 찾지만 생성된 클래스에 인덱서 메서드가 없으므로 해결하지 못했습니다.

이 문제를 해결하는 가장 쉬운 방법은 인덱서 결과를 엄격한 수준으로 되돌리는 것입니다.Range로컬 변수:

enter image description here

그러면 당신의 시험은 실패할 것입니다. 왜냐하면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는 코드가 디버그 친화적 코드가 될 것이기 때문에 테스트를 통과할 것이기 때문이 아니라 "원자 OPS(멀티 라인) 및 메소드"로 집합 호출을 끊어야 합니다.(저는 당신의 코드가 작성된 시점으로부터 최소 10번 더 읽히는 "11번째 규칙"이라고 부릅니다.그러므로 컴파일러가 타동적인 로컬 변수를 제거하고 디버그 친화적인 코드로 만들 수 있도록 하십시오.

여기서는 c#에서 동적이 어떻게 작동하는지에 대한 링크와 함께 간단하고 짧은 설명을 읽을 수 있습니다.

여기에서는 캐슬 다이나믹 프록시에 대해 자세히 볼 수 있습니다.

그건 그렇고, 당신은 또한 다음을 할 수도 있습니다.

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

가치를 받다

언급URL : https://stackoverflow.com/questions/50524000/how-to-mock-rows-in-a-excel-vsto-plugin