atribuir tipo à variável, usar variável com classe estática genérica
-
19-09-2019 - |
Pergunta
Estou trabalhando em um serviço web C# com uma classe estática genérica que usa um tipo.Eu queria saber por que isso não compila:
Type type1 = typeof(MySnazzyType);
Assert.AreEqual(0, ConnectionPool_Accessor<type1>._pool.Count);
Dá esse erro:
O tipo ou nome do namespace 'type1' não foi encontrado (falta uma diretiva using ou uma referência assembly?)
E o ReSharper, quando passo o mouse type1
nessa segunda linha de código, diz "Tipo ou nome do namespace esperado".Bem, type1
é um tipo!É uma variável do tipo Type
!Também não funciona se eu fizer:
Type type1 = typeof(MySnazzyType);
Assert.AreEqual(0, ConnectionPool_Accessor<typeof(type1)>._pool.Count);
Eu esperava atribuir meus tipos a alguns tipos diferentes Type
variáveis e apenas usá-las para testar as diferentes classes estáticas genéricas, em vez de digitar MySnazzyType
cada vez.Alguma idéia, ou estou preso em fazer:
Assert.AreEqual(0, ConnectionPool_Accessor<MySnazzyType>._pool.Count);
Editar: esclarecer, MySnazzyType
é não uma classe genérica, nem herda de uma classe genérica.A única classe genérica aqui é ConnectionPool_Accessor
.
Graças ao comentário de Pavel "Essencialmente, seu problema é que C# é uma linguagem de tipo estaticamente", agora sei que Ruby me estragou.;)
Solução
Em primeiro lugar, o ReSharper está realmente correto.Não é um tipo, é um variável.É verdade que é uma variável que contém o objeto de reflexão que corresponde a um tipo, mas isso não é suficiente.
Entre colchetes <...> você deve escrever o nome de um tipo, não o nome de qualquer outro identificador.
No entanto, você pode construir objetos genéricos por meio de reflexão e acessar suas propriedades, mesmo as estáticas; portanto, você deve ser capaz de reescrever o código para fazer isso. No entanto, você já olhou para o NUnit 2.5?
A partir das notas de versão mais recentes, parece que as classes de teste de unidade agora podem ser genéricas e você pode especificar com um atributo na classe de teste quais tipos serão testados.
Isso permitiria que você escrevesse algo assim (observe, eu não testei isso, apenas procurei os nomes dos novos atributos na documentação):
[TestFixture(typeof(MySnazzyType))]
[TestFixture(typeof(MyOtherSnazzyType))]
public class Tests<T>
{
[Test]
public void PoolCount_IsZero()
{
Assert.AreEqual(0, ConnectionPool_Accessor<T>._pool.Count);
}
}
Outras dicas
Os tipos genéricos são avaliados em tempo de compilação, não em tempo de execução.Como não pode ser determinado em tempo de execução o que type1
será, esta construção não é permitida.
Na verdade, isso é o que o Resharper diz: type1
não é um tipo, é uma variável do tipo Type
, (assim como poderia ser um objeto do tipo String
).
O TestFixture
atributo deve configurá-lo, mas só por diversão:se você quiser fazer tudo isso em tempo de execução, poderá fazê-lo usando reflexão.
Type poolType = typeof(ConnectionPool_Accessor<>);
Type snazzyType = typeof(MySnazzyType); // Or however you want to get the appropriate Type
poolType.MakeGenericType(snazzyType);
Você poderia então fazer o que quiser usando a reflexão em poolType
.É claro que isso será um grande problema, a menos que você use a digitação dinâmica do C# 4.0.