How to deal with private member accessor and collections?
I have a class hierachy like this
public class A
{
protected开发者_JAVA百科 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'
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 object
s 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);
}
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).
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.
It seems to me that you are testing an implementation detail, not the intended API level for users of your library.
精彩评论