在反射中查找泛型类型

时间:2015-01-09 13:05:36

标签: c# generics reflection

我有一小段代码,检查,我们是否存在类。

首先我加载所有可用的类型:

List<Type> types = new List<Type>();
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
{
    try
    {
        types.AddRange(asm.GetTypes());
    }
    catch (ReflectionTypeLoadException e)
    {
        types.AddRange(e.Types.Where(t => t != null));
    }
}

比我的concat命名空间和类名(应该检查):

string fullName = ns.Trim() + "." + classToProof.Trim();

在和,我检查课程是否存在:

int found = types.Where(innerItem => innerItem.FullName == fullName).ToList().Count;

但是我有问题,如果我检查泛型类,例如System.Collections.Generic.Dictionaryfound总是 0 (应该是1)。

有没有人有想法,为什么会这样?

解决方案

List<string> types = new List<string>();

foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
{
    try
    {
        types.AddRange(asm.GetTypes().Select(item => (!item.FullName.Contains("`") ? item.FullName : item.FullName.Substring(0, item.FullName.IndexOf("`")))));
    }
    catch (ReflectionTypeLoadException e)
    {
        types.AddRange(e.Types.Where(t => t != null).Select(item => (!item.FullName.Contains("`") ? item.FullName : item.FullName.Substring(0, item.FullName.IndexOf("`")))));
    }
}

我从全名中删除了所有`,并填写了准备好的字符串列表。

谢谢

2 个答案:

答案 0 :(得分:2)

这可能是因为泛型使用``带有一个数字,表示通用参数计数如 List`1 。你的类型名称没有它。为了防止这种情况,我建议直接检查类型而不是名称:

 types.Where(t => t == typeof(Dictionary<,>))

或者您可以使用SubstringIndexOf来获取“

之前的部分
int found = types
 .Where(t => t.IsGenericType
                ? t.FullName.Substring(0,t.FullName.IndexOf('`'))  == fullName 
                : t.FullName == fullName).ToList().Count;

答案 1 :(得分:0)

很抱歉,但Matias是对的,你的解决方案在技术上是错误的。

主要问题是,在具有相同名称但具有不同类型args的命名空间类型中,可以同时共存。所以这是有效的:

SomeNameSpace
{
    public class MyType {}     // FullName: SomeNameSpace.MyType   
    public class MyType<T> {}  // FullName: SomeNameSpace.MyType`1
}

因此,当您尝试查找System.Collections.Generic.Dictionary时,您实际上是在尝试查找名为&#34; System.Collections.Generic.Dictionary&#34;的类。但是有0个类型的参数。 System.Collections.Generic中没有这样的类型。

如果你想找到System.Collections.Generic.Dictionary,那可以,但是那个类型的全名是&#34; System.Collections.Generic.Dictionary`2&#34;,其中反引号后跟数字2意味着你谈论一个带有2种类型args的泛型类型。

您的解决方案可能有效,并且可能解决您的具体问题,但您必须了解它在技术上是错误的,因为如果您删除了通用类型名称的反引号部分,那么您实际上将类型的所有通用版本合并到一个名字。所以要注意,并考虑使用原始代码(可以),以及通用类型的正确名称。