今天用了Type.GetInface(string typeName)这个API,觉得能比较好的得到当前Type是否实现了一个范型定义的interface,比如,IList<T>。但是在写Unit test之后却不可思议的发现Unit test挂了。研究了半天,才知道其中竟然有这个曲折,且看示例。
class Program
{
static void Main(string[] args)
{
Console.WriteLine(typeof(Normal).GetInterface(typeof(INormal).FullName) != null);
Console.WriteLine(typeof(Nested).GetInterface(typeof(INested).FullName) != null);
Console.WriteLine(typeof(Special).GetInterface(typeof(INested).FullName) != null);
Console.Read();
}
class Nested : INested
{
}
public interface INested
{
}
}
class Normal : INormal
{
}
interface INormal
{
}
class Special : Program.INested
{
}
可以发现运行的结果,第一行是True,第二行、第三行是False。也就是GetInterface这个API对Nested interface不能支持,应该是.net的bug。原来可能因为typeof(INested).FullName = ConsoleApplication1.Program+INested含有+这个符号,所以没有处理好吧。
但是是不是如果没有这个问题,我们就可以放心的使用这个API了吗?是不是我们只要保证传入的Interface不是nested就可以了呢?我觉得从代码安全性上是值得商榷的。因为该API是通过一个type name来寻找的interface的。首先,我们要使用Type的FullName,因为仅用Name的话很容易找错。但是FullName也不是绝对的,我可以定义两个interface拥有相同的FullName,但是却是两种定义。这时候你的方法可能就被人Hack过去了。所以我不推荐使用这个API,除非你在得到结果以后还能更进一步的check。写了下面一段方法来代替GetInterface()。
static class TypeExt
{
public static Type GetInterface(this Type type, Type interfaceType)
{
Type[] interfaceTypes = type.GetInterfaces();
foreach (Type i in interfaceTypes)
{
if (i == interfaceType)
{
return i;
}
else if (i.IsGenericType)
{
if (i.GetGenericTypeDefinition() == interfaceType)
{
return i;
}
}
}
return null;
}
}