0

我有这样的班级层次结构

public class A
{
    protected class B 
    {
        String Name { get; set; }
    }

    protected class C : KeyedCollection<String, B> 
    {
        // ...
    }

    protected C Collection { get; }

    // ...

    public A Copy () 
    {
        // Creates a deep copy of this instance.
    }
}

现在我想编写一个单元测试来比较 A 的两个实例是否在属性 KeyedCollection 中具有相同的项目 B。但是,我无法在 A 实例中执行 foreach 循环。我试过的,

[TestClass]
public class TestClass
{
    public void ATest()
    {
        A original = new A();
        A copy = A.Copy();

        // ...

        A_Accessor originalAccessor = A_Accessor.AttachShadow(original);
        A_Accessor copyAccessor = A_Accessor.AttachShadow(copy);

        foreach(var originalItem in originalAccessor.Collection)
        {
            var copyItem = copyAccessor[originalItem.Name];
            Assert.AreEqual(originalItem, copyItem);
        }
    }
}

这段代码甚至无法编译,因为 C 类访问器没有实现 IEnumerable 接口(它没有实现 KeyedCollection 类的任何接口)。有谁知道我该如何克服这个问题?

我收到的错误消息是

foreach 语句不能对“C”类型的变量进行操作,因为“A_Accessor.C”不包含“GetEnumerator”的公共定义

4

4 回答 4

0

目前尚不清楚您是如何设法通过受保护的属性公开私有类类型的,但作为 C派生自 KeyedCollection它应该已经继承了IEnumerable<B>.

目前尚不清楚您要做什么,但是您仍然应该能够迭代集合……如果您甚至可以看到该属性。我怀疑您的代码由于其他原因无法编译 - 因为C尽管受到保护,但它是根据私有成员类型声明的,并且因为您首先尝试C从不同的类访问(尽管它受到保护)。

于 2010-02-01T17:42:40.623 回答
0

我只是试图编译你的例子:正如预期的那样,我得到了一个错误

Inconsistent accessibility: field type 'A.C' is less accessible than field 'A.Collection'.

基本上这意味着您不能使用私有类型声明受保护的属性。所以这不是你的测试代码的问题,而是要测试的代码......

编辑

您可以使用originalAccessor.Collection.Target并将其转换为ICollection. 当然,object在这种情况下您只能枚举 s ,因此您必须再次转换每个项目:

foreach (var item in (originalAccessor.Collection.Target as ICollection)) {
   A_Accessor.B casted = A_Accessor.B.AttachShadow(item);
   var copyItem = copyAccessor[casted.Name];
   Assert.AreEqual(casted, copyItem);
}
于 2010-02-01T17:53:03.503 回答
0

实际上,我找到的解决方案与 Martin 的建议非常相似:

var originalItems = 
    from item in (originalAccessor.Collection.Target as IEnumerable).Cast<Object>()
    select A_Accessor.B.AttachShadow(item);

var copyItems = 
    from item in (copyAccessor.Collection.Target as IEnumerable).Cast<Object>()
    select A_Accessor.B.AttachShadow(item); 

foreach(var original in originalItems) 
{ 
    String originalName = original.Name;
    A_Accessor.B copy = copyItems.First(b => b.Name == originalName);

    // ...
}

感谢您的所有协助!卡洛斯。

于 2010-02-01T18:53:00.060 回答
0

在我看来,您正在测试一个实现细节,而不是您的库用户的预期 API 级别。

于 2010-02-02T10:52:03.320 回答