How to pattern match a generic Type
c#, generics
Solution
Use `GetGenericTypeDefinition` method instead.
Type testType;
Type firstCheck = typeof(System.Linq.Expressions.Expression<>);
bool isExpression =
(testType.IsGenericType && testType.GetGenericTypeDefinition() == firstCheck)
|| (!testType.IsGenericType && testType == firstCheck);
Update
Here is a recurrence method to check if type match given pattern:
private static bool IsTypeCompatibile(Type pattern, Type test, Type placeholder)
{
if (pattern == test || pattern == placeholder)
return true;
if(pattern.IsGenericType)
{
if (!test.IsGenericType || pattern.GetGenericTypeDefinition() != test.GetGenericTypeDefinition())
return false;
var patternGenericTypes = pattern.GetGenericArguments();
var testGenericTypes = test.GetGenericArguments();
return patternGenericTypes.Length == testGenericTypes.Length
&& patternGenericTypes.Zip(testGenericTypes, (p, t) => IsTypeCompatibile(p, t, placeholder)).All(x => x);
}
return false;
}
Usage:
var pattern = typeof(Expression<Func<Placeholder, bool>>);
var type1 = typeof(Expression<Func<string, bool>>);
var type2 = typeof(Expression<string>);
var type3 = typeof(Expression<Func<string, string, bool>>);
Console.WriteLine(IsTypeCompatibile(pattern, type1, typeof(Placeholder)));
Console.WriteLine(IsTypeCompatibile(pattern, type2, typeof(Placeholder)));
Console.WriteLine(IsTypeCompatibile(pattern, type3, typeof(Placeholder)));
Prints
True
False
False
Of course, you need to define `Placeholder` class:
public class Placeholder
{ }
Problem
I'd like to detect whether a type matches a certain Type pattern. The pattern in this case is `Expression<Func<T, bool>>`, where T can match any type (the standard interpretation). Given this pattern, ``` Expression<Func<string, bool>> v; //matches Expression<string> v; //doesn't match Expression<Func<string, string, bool>> v; //doesn't match ``` My strategy is compare whether the beginning of the FullName of the test type matches the FullName of a generic type. If it does, peels a layer off via GetGenericArguments, then repeat the check. Code of the first check: ``` Type testType; Type firstCheck = (System.Linq.Expressions.Expression<>); bool isExpression = testType.FullName.StartsWith(firstCheck.FullName); ``` This seems to work, but rather ugly. Moreover, it is not a generic solution; each pattern requires its own checker function. Does anyone have a better solution? A related question is how to best express a pattern?