Print Article
Add to your CodeProject bookmarks
Comment on this article
Report this article as inappropriate
C# Generic Type GeneratorCombinatorial generation of C# generic types.
IntroductionI’m posting some C# code that builds all possible combinations of a generic type. The user specifies a generic type with unresolved generic parameters (e.g. In the example I’ve just given, Tuple
BackgroundAlthough the introductory example was fairly trivial, the code necessary to solve the general problem is not. However, anyone with a basic understanding of .Net generics should be able to examine and modify the code. MotivationMy motivation to create this utility was improved testing. While working on a C# application, I decided to use the policy design pattern. Although I could have also used the strategy design pattern, I felt policies were the best approach. Strategies are typically constructor arguments passed to a strategy host. In C++, policies are typically template arguments applied to a policy host; in C#, I of course use the analog to templates, which are generics. Here are a few reasons you might favor policies (via generic arguments) over strategies (via constructor arguments):
If none of these reasons seem relevant to your application, and they probably won’t most of the time, strategies may be a superior choice. One specific reason you might favor strategies over policies is the ugly look and somewhat laborious typing involved in supporting multiple generic parameters on a class. In fact, FxCop even has a rule for this! Getting back to the point, imagine a C# policy host containing four policy types: public interface IMyGame
{
int MyTestableMethod();
}
public class MyGame
As part of my test plan, I would like to run tests on each version of My overall goal would be to somehow create all 256 types, make instances of those types through reflection, and then cast those instances to a simple, yet testable, interface that doesn't vary based on the generic parameters in question (in our example, this interface is At first glance, it appears I can just set up four nested for-loops and create the 256 types without much thought. But remember - policies may also be generic types, and they can be arbitrarily composable with each other: public class MyGraphicsPolicy1
The complexity doesn't end there. Consider arbitrary generic constraints: public class MyGraphicsPolicy2
We won’t be able to solve this problem with four for-loops after all. This problem can be presented very similarly either in terms of generic arguments or constructor arguments. Regardless of which way it's presented, it has plenty of complexity (with similarities to the knapsack problem). When presented in terms of generic arguments, there are unique concerns that must be addressed. This code sets out to address those concerns while solving the general problem. Using the CodeThe code uses C# 4.0 and .Net 4.0 libraries. To date, I’ve only used and tested it in a Windows environment within Visual Studio 2010. I’m also including some auxiliary code that may be of use to anyone experimenting with Ivo Manolov is developing a very useful test suite called TestApi. It has an excellent combinatorial test library, but, as of yet, it does not support the combinatorial testing of generic types. I recommend using TestApi for combinatorial testing in general. In fact, I use it to test certain aspects of this code (this dependency is very light and can be easily severed if desired). In other applications where there are generic and non-generic combinatorial testing requirements, I use In terms of the public interface, here are the simplest methods: static public class GenericTypeGenerator
{
static public IEnumerable
Using the simplest method would look like this: foreach(Type builtType in GenericTypeGenerator.BuildTypes(typeof(Func<,,>),
new Type
{
typeof(int),
typeof(float),
typeof(string)
}))
{
// Do something with builtType. For example, create an instance of it with
// reflection and cast to a testable interface…
}
By default, non-generic types and generic types with resolved generic parameters can be used any number of times within a single built type. However, generic types with unresolved generic parameters can only be used once (or as many times as specified in the enumerable of available types). Without this default rule, it would be too easy to have infinite recursion. As you can see, An easy way to see how [TestMethod]
public void Test_CyclicalNakedConstraints()
{
VerifyBuiltTypes(
typeof(CyclicalNakedConstraints<,>),
new Type
{
typeof(CyclicalNakedConstraints_TImpl),
typeof(CyclicalNakedConstraints_UImpl),
typeof(CyclicalNakedConstraints_TAndUImpl)
},
new Type
{
typeof(CyclicalNakedConstraints
The first parameter is the type to build, the second parameter is the available types, and the third parameter is the expected built types. Included are plenty of tests that illustrate what results to expect and what issues to watch out for. Points of InterestHere’s a portion of a test that accompanies the code. Besides being part of a test, it also serves to illustrate a particular point. private class T_U_tripleNestedIDictionary
Take a rough guess at how many types this produces, as well as how many unique types have to be evaluated by the underlying algorithm. Returned: 2 Evaluated: 750+ It wouldn’t take much more for the evaluated types to top 10,000. The moral of the story is know that it can be costly to specify available types that are composable with each other. History
LicenseThis article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL) About the Author
Comments and Discussions
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||