Question

Je travaille dans un service Web C # avec une classe statique générique qui prend un type. Je me demandais pourquoi cela ne compile pas:

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

Il donne cette erreur:

Le type ou le nom de l'espace de noms «Type1» ne peut être trouvé (manquez-vous une directive ou une référence d'assemblage?)

Et Resharper, quand je survole type1 Dans cette deuxième ligne de code, indique "Type ou nom d'espace de noms attendus". Bien, type1 est un type! C'est une variable de type Type! Cela ne fonctionne pas non plus si je le fais:

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

J'espérais attribuer mes types à quelques différents Type variables et utiliser simplement celles pour tester les différentes classes statiques génériques, au lieu de taper MySnazzyType chaque fois. Toutes les idées, ou suis-je coincé avec le fait:

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

Éditer: clarifier, MySnazzyType est ne pas Une classe générique, ni hériter d'une classe générique. La seule classe générique ici est ConnectionPool_Accessor.

Grâce au commentaire de Pavel "Essentiellement, votre problème est que C # est un langage dactylographié statiquement", je sais maintenant que Ruby m'a gâté. ;)

Était-ce utile?

La solution

Tout d'abord, Resharper est en fait correct. Ce n'est pas un taper, c'est un variable. Certes, c'est une variable qui tient l'objet de réflexion qui correspond à un type, mais cela ne suffit pas.

Entre les supports <...>, vous devez écrire le nom d'un type, pas le nom d'un autre identifiant.

Vous pouvez cependant construire des objets génériques par la réflexion, et accéder à leurs propriétés, même statiques, vous devriez donc être en mesure de réécrire le code pour ce faire, cependant, avez-vous regardé Nunit 2.5?

D'après les dernières notes de version, il semble que les classes de test unitaires peuvent désormais être génériques, et vous pouvez spécifier avec un attribut sur la classe de test avec laquelle les types avec lesquels le tester.

Cela vous permettrait d'écrire quelque chose comme ça (note, je n'ai pas testé cela, je n'ai recherché que les noms des nouveaux attributs dans la documentation):

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

Autres conseils

Les types génériques sont évalués à Temps de compilation, pas dedans Durée. Puisqu'il ne peut pas être déterminé au moment de l'exécution type1 sera, cette construction n'est pas autorisée.

C'est en fait ce que dit Resharper: type1 n'est pas un type, c'est une variable du type Type, (tout comme cela pourrait être un objet du type String).

La TestFixture L'attribut doit vous configurer, mais juste pour le diable: si vous vouliez faire tout cela au moment de l'exécution, vous pouvez le faire en utilisant la réflexion.

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

Vous pouvez ensuite procéder à faire ce que vous voulez en utilisant la réflexion sur poolType. Bien sûr, ce sera une douleur majeure dans le cul, sauf si vous utilisez le typage dynamique C # 4.0.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top