assign type to variable, use variable with generic static class
-
19-09-2019 - |
Question
I'm working in a C# web service with a generic static class that takes a type. I was wondering why this does not compile:
Type type1 = typeof(MySnazzyType);
Assert.AreEqual(0, ConnectionPool_Accessor<type1>._pool.Count);
It gives this error:
The type or namespace name 'type1' could not be found (are you missing a using directive or an assembly reference?)
And ReSharper, when I hover over type1
in that second line of code, says "Type or namespace name expected". Well, type1
is a type! It's a variable of type Type
! It also doesn't work if I do:
Type type1 = typeof(MySnazzyType);
Assert.AreEqual(0, ConnectionPool_Accessor<typeof(type1)>._pool.Count);
I was hoping to assign my types to a couple of different Type
variables and just use those in testing the different generic static classes, instead of typing out MySnazzyType
each time. Any ideas, or am I stuck with doing:
Assert.AreEqual(0, ConnectionPool_Accessor<MySnazzyType>._pool.Count);
Edit: to clarify, MySnazzyType
is not a generic class, nor does it inherit from a generic class. The only generic class here is ConnectionPool_Accessor
.
Thanks to Pavel's comment "Essentially, your problem is that C# is a statically typed language", I now know that Ruby has spoiled me. ;)
Solution
First of all, ReSharper is actually correct. It isn't a type, it's a variable. Granted, it's a variable that is holding the reflection object that corresponds to a type, but that isn't enough.
Between the <...> brackets, you have to write the name of a type, not the name of any other identifier.
You can construct generic objects through reflection, however, and access their properties, even static ones, so you should be able to rewrite the code to do that, however, have you looked at NUnit 2.5?
From the latest release notes, it appears that unit test classes can now be generic, and you can specify with an attribute on the test class which types to test it with.
This would allow you to write something like this (note, I have not tested this, I only looked up the names of the new attributes in the documentation):
[TestFixture(typeof(MySnazzyType))]
[TestFixture(typeof(MyOtherSnazzyType))]
public class Tests<T>
{
[Test]
public void PoolCount_IsZero()
{
Assert.AreEqual(0, ConnectionPool_Accessor<T>._pool.Count);
}
}
OTHER TIPS
Generic types are evaluated at compile time, not in runtime. Since it cannot be determined at runtime time what type1
will be, this construct is not allowed.
This is actually what Resharper says: type1
is not a Type, it's a variable of the type Type
, (just as it could be an object of the type String
).
The TestFixture
attribute should set you up, but just for the heck of it: if you wanted to do all this at runtime, you could do so using reflection.
Type poolType = typeof(ConnectionPool_Accessor<>);
Type snazzyType = typeof(MySnazzyType); // Or however you want to get the appropriate Type
poolType.MakeGenericType(snazzyType);
You could then proceed to do whatever you want using reflection on poolType
. Of course, that will be a major pain in the butt unless you use C# 4.0 dynamic typing.