如何处理私有成员访问器和集合?

发布于 2024-08-19 17:34:53 字数 1150 浏览 8 评论 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”的公共定义

I have a class hierachy like this

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.
    }
}

Now I'd like to write a unit test to compare if two instances of A have the same items B inside the property KeyedCollection. However, I'm not being able to perform a foreach loop into the A instances. What I had tried,

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

This code doesn't even compile because the C class accessor doesn't implements the IEnumerable interface (it doesn't implement any interface from KeyedCollection class). Does anyone have an idea about how can I overcome this issue?

The error message I'm getting is

foreach statement cannot operate on variables of type 'C' because 'A_Accessor.C' does not contain a public definition for 'GetEnumerator'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

水水月牙 2024-08-26 17:34:53

我只是尝试编译您的示例:正如预期的那样,我收到错误

可访问性不一致:字段类型“AC”比字段“A.Collection”更难访问

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

编辑

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

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

I just tried to compile your example: As expected I got an Error

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

Basically that means that you cannot declare a protected property using a private type. So it's not a problem with your test code but with the code to be tested ...

EDIT

You could use originalAccessor.Collection.Target and cast it to ICollection. Of course you can only enumerate over objects in this case, so you'll have to cast each item again:

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);
}
自找没趣 2024-08-26 17:34:53

目前尚不清楚如何通过受保护的属性来公开私有类类型,但由于 C 派生自 KeyedCollection 它应该已经继承了 <代码>IEnumerable

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

It's not clear how you're managing to expose a private class type via a protected property to start with, but as C derives from KeyedCollection it should already inherit the implementation of IEnumerable<B>.

It's not really clear what you're trying to do, but you should still be able to iterate over the collection... if you can even see the property. I suspect your code doesn't compile for other reasons - because C is declared in terms of a private member type, despite being protected, and because you're trying to access C from a different class in the first place (despite it being protected).

默嘫て 2024-08-26 17:34:53

事实上,我找到的解决方案与马丁的建议非常相似:

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

    // ...
}

感谢您的帮助!
卡洛斯.

Actually, the solution I found was very similiar to Martin's suggestion:

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

    // ...
}

Thanks for all your assitance!
Carlos.

睡美人的小仙女 2024-08-26 17:34:53

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

It seems to me that you are testing an implementation detail, not the intended API level for users of your library.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文