如何通过类型名称获取泛型接口的类型?

3

好的,这是我的问题:

我有一个XML文件,其中记录了一种方法及其参数。该XML文件记录了以下.NET通用接口类型名称的ID值列表:

System.Collections.Generic.IList`1[CoreLib.Domain.MyClass]

我知道大多数这些参数都将是通用列表或字典。当我尝试在从xml中读取的字符串值上使用GetType时,它会返回null,如果我尝试将throw exception标志设置为true,则会抛出以下消息:“无法从程序集'TestLibrary,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'中加载类型'CoreLib.Domain.MyClass'。”获取可以返回实际类型并可填充的内容的最佳策略是什么?提前感谢您!更新:我已尝试添加到字符串名称的程序集引用,如下所示:
Type.GetType("System.Collections.Generic.List`1[CoreLib.Domain.MyClass,CoreLibrary]")

或者

coreLibAssembly.GetType("System.Collections.Generic.List`1[CoreLib.Domain.MyClass,CoreLibrary]")

两者都会导致空对象,或者如果我要求抛出异常,则与我没有指定程序集名称时收到的相同消息相同。我还尝试使用程序集绑定日志查看器,但没有应用程序出现在列表中,在运行我的代码后似乎没有任何东西出现在应用程序中(它位于由nunit执行的测试项目中)。

有什么想法吗?


我也尝试在泛型的T定义中包含程序集的完整名称,但仍然没有成功。 - Nathan Tregillus
2个回答

1

通常你可以将字符串按照现有形式传递到Type.GetType()。例如:

Type t = Type.GetType("System.Collections.Generic.Dictionary`2[System.String,System.Int32]");

我怀疑在你的情况下,CLR 不知道如何解析类型 CoreLib.Domain.MyClass。你可能需要通过指定程序集来帮助它,就像这个例子从 MSDN 中获取所示:
Type.GetType("System.Collections.Generic.Dictionary`2[System.String,[MyType,MyAssembly]]")

如果在指定程序集后仍然出现“崩溃”(下次建议您更好地定义,例如使用特定的错误、异常或堆栈跟踪:-),请尝试以管理员身份运行Fusion Log Viewer(否则它会悄悄失败)以记录绑定失败。

我已经尝试了这两种方法,但一直遇到汇编问题:首先,集合命名空间在mscorlib中,所以我无法使用Assembly.GetType...而且如果我尝试使用指定程序集名称的Type.GetType,它会忽略给定的程序集名称,并仍然在我的测试库中查找对象。(很抱歉有这么多注释,我真的需要让它工作!) - Nathan Tregillus
实际上这并没有起作用。发生的情况是Type.GetType在某种程度上认为泛型中的程序集名称是另一个类,并试图将其识别为类型。 - Nathan Tregillus
我认为你可能需要一个额外的[]。你没有完全按照MSDN所示的方式操作。尝试使用....List`1[[CoreLib.Domain.MyClass,CoreLibrary]]。 - Eric J.
我会尝试一下,但在操作字符串后,我开始解析最初生成的类型字符串。我希望尽可能接近标准类型而无需修改它。我的解决方案似乎在我只有三个dlls:mscorlib、CorLib和TestLibrary的情况下工作得很好。 - Nathan Tregillus

0

我已经解决了问题。问题在于程序集的引用方式,以及GetType方法如何确定程序集的位置。最终,我通过使用程序集解析器匿名委托来解决了这个问题:

    result = Type.GetType(typeName + ",mscorlib", //<-- needing to identify the mscorlib  for generics!
        //this anonymous delegate method is used by the GetType Framework to identify and return the correct assembly for the given assembly name.
        //most of this is default, except to handle the mscorlib library
        delegate(AssemblyName potentialAssembly)
        {
            if (potentialAssembly.Name == coreLibAssembly.FullName)
                return coreLibAssembly; // this was never called, I had to check the namespace within the rest of my code
            else if (potentialAssembly != null)
                return Assembly.Load(potentialAssembly);
            else
                return null;
        },
        //this anonymous delegate is used to return the type specific to the assembly. this method is called for each nested generic, 
        //so we don't have to parse the type string name by hand.
        delegate(Assembly potentialAssembly, string inputTypeName, bool ignoreCase)
        {
            if (inputTypeName.StartsWith("CoreLib.Domain"))
                return coreLibAssembly.GetType(inputTypeName, true, ignoreCase);
            else if (potentialAssembly != null)
                return potentialAssembly.GetType(inputTypeName, true, ignoreCase);
            else
                return Type.GetType(inputTypeName, true, ignoreCase);
        }, true);

现在,如果通用的 Type.GetType(string typeName) 方法不起作用,我会使用这段代码来解析类型字符串,并将程序集与给定的 typeName 字符串变量中对应的类型名称进行匹配。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接