Domanda

Sto lavorando in un servizio Web C# con una classe statica generica che prende un tipo. Mi chiedevo perché questo non si compila:

Type type1 = typeof(MySnazzyType);
Assert.AreEqual(0, ConnectionPool_Accessor<type1>._pool.Count);

Dà questo errore:

Non è stato possibile trovare il nome di tipo o spazio nomi 'type1' (ti manca una direttiva usando o un riferimento di assembly?)

E risharper, quando mi muovo type1 In quella seconda riga di codice, dice "Nome tipo o spazio nomi previsto". Bene, type1 è un tipo! È una variabile di tipo Type! Inoltre non funziona se lo faccio:

Type type1 = typeof(MySnazzyType);
Assert.AreEqual(0, ConnectionPool_Accessor<typeof(type1)>._pool.Count);

Speravo di assegnare i miei tipi a un paio di diversi Type variabili e usa semplicemente quelle nel testare le diverse classi statiche generiche, invece di digitare MySnazzyType ogni volta. Qualsiasi idea, o sono bloccato nel fare:

Assert.AreEqual(0, ConnectionPool_Accessor<MySnazzyType>._pool.Count);

Modificare: per chiarire, MySnazzyType è non Una classe generica, né eredita da una classe generica. L'unica classe generica qui è ConnectionPool_Accessor.

Grazie al commento di Pavel "Essenzialmente, il tuo problema è che C# è un linguaggio tipizzato staticamente", ora so che Ruby mi ha rovinato. ;)

È stato utile?

Soluzione

Prima di tutto, Resharper è in realtà corretto. Non è un genere, è un variabile. Certo, è una variabile che tiene l'oggetto di riflessione che corrisponde a un tipo, ma non è sufficiente.

Tra le staffe <...>, devi scrivere il nome di un tipo, non il nome di nessun altro identificatore.

Puoi costruire oggetti generici attraverso la riflessione, tuttavia, e accedere alle loro proprietà, anche di quelle statiche, quindi dovresti essere in grado di riscrivere il codice per farlo, tuttavia, hai guardato NUNIT 2.5?

Dalle ultime note di rilascio, sembra che ora le classi di test unitarie possano essere generiche e puoi specificare con un attributo sulla classe di prova con quali tipi per testarlo.

Questo ti permetterebbe di scrivere qualcosa del genere (nota, non ho testato questo, ho cercato solo i nomi dei nuovi attributi nella documentazione):

[TestFixture(typeof(MySnazzyType))]
[TestFixture(typeof(MyOtherSnazzyType))]
public class Tests<T>
{
    [Test]
    public void PoolCount_IsZero()
    {
        Assert.AreEqual(0, ConnectionPool_Accessor<T>._pool.Count);
    }
}

Altri suggerimenti

I tipi generici vengono valutati a Tempo di compilazione, Non in Runtime. Dal momento che non può essere determinato al momento del runtime cosa type1 sarà, questo costrutto non è consentito.

Questo è in realtà ciò che dice Resharper: type1 non è un tipo, è una variabile del tipo Type, (proprio come potrebbe essere un oggetto del tipo String).

Il TestFixture L'attributo dovrebbe prepararti, ma solo per diamine: se volevi fare tutto questo in fase di esecuzione, potresti farlo usando la riflessione.

Type poolType = typeof(ConnectionPool_Accessor<>);
Type snazzyType = typeof(MySnazzyType); // Or however you want to get the appropriate Type
poolType.MakeGenericType(snazzyType);

Potresti quindi procedere a fare quello che vuoi usare la riflessione su poolType. Naturalmente, questo sarà un grande dolore nel sedere a meno che non si utilizzi la digitazione dinamica C# 4.0.

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