Domanda

Ho un heerachy di classe come questo

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

Ora vorrei scrivere un test unitario per confrontare se due istanze di A hanno gli stessi elementi B all'interno della proprietà KeyedCollection. Tuttavia, non sono in grado di eseguire un ciclo foreach nei casi A. Quello che avevo provato

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

Questo codice non si compila nemmeno perché l'accessore della classe C non implementa l'interfaccia ienumerable (non implementa alcuna interfaccia dalla classe KeyEdCollection). Qualcuno ha un'idea di come posso superare questo problema?

Il messaggio di errore che sto ricevendo è

L'istruzione foreach non può operare su variabili di tipo "c" perché "a_accessor.c" non contiene una definizione pubblica per "getenumerator"

È stato utile?

Soluzione

Ho appena provato a compilare il tuo esempio: come previsto ho ricevuto un errore

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

Fondamentalmente ciò significa che non è possibile dichiarare una proprietà protetta utilizzando un tipo privato. Quindi non è un problema con il codice di prova ma con il codice da testare ...

MODIFICARE

Potresti usare originalAccessor.Collection.Target e lanciarlo a ICollection. Ovviamente puoi solo elencare objectS In questo caso, quindi dovrai lanciare di nuovo ogni articolo:

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

Altri suggerimenti

Non è chiaro come stai riuscendo a esporre un tipo di classe privato tramite una proprietà protetta per cominciare, ma come c deriva da KeyedCollection dovrebbe già ereditare l'implementazione di IEnumerable<B>.

Non è davvero chiaro cosa stai cercando di fare, ma dovresti comunque essere in grado di iterare sulla collezione ... se riesci ad vedere la proprietà. Sospetto che il tuo codice non si compila per altri motivi, perché C è dichiarato in termini di tipo di membro privato, nonostante sia protetto e perché stai cercando di accedere C da una classe diversa in primo luogo (nonostante sia protetto).

In realtà, la soluzione che ho trovato è stata molto simile al suggerimento di 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);

    // ...
}

Grazie per tutta la tua assistenza! Carlos.

Mi sembra che tu stia testando un dettaglio di implementazione, non il livello API previsto per gli utenti della tua libreria.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top