动态调用抛出错误"对象的类型' myObject'无法转换为' myObject' "

时间:2017-11-15 01:56:38

标签: c# reflection

我创建了一个动态创建类型的对象,并且我试图调用运行时加载的函数。

使用以下命令调用异常: {System.ArgumentException:类型对象' UserClasses.re_Constituent'无法转换为' UserClasses.re_Constituent'。}

(是的,这两个类是相同的)

该类的代码,以及之前根据https://stackoverflow.com/a/3024112/432976生成和编译调用函数的代码

有谁知道错误的来源?

magicValue Invoke()

中的以下代码异常
namespace UserClasses
{
  public class re_Constituent : Node
  {
    public string id;
    ... other fields
  }
}

在调用代码行暂停时检查:

myMethodInfo是: {System.Collections.Generic.List`1 [UserClasses.Node] ConvertToCore(UserClasses.re_Constituent)}

methodInfo期望的参数类型是: " UserClasses.re_Constituent,dynamicGen_reApi_3,Version = 0.0.0.0,Culture = neutral,PublicKeyToken = null"

传递给JSON反序列化器(Jil)的类型列为: " UserClasses.re_Constituent,dynamicGen_reApi_3,Version = 0.0.0.0,Culture = neutral,PublicKeyToken = null"

result.GetType()AssemblyQualifiedName: " UserClasses.re_Constituent,dynamicGen_reApi_3,Version = 0.0.0.0,Culture = neutral,PublicKeyToken = null"

re_Constituent在一个单独的动态加载的dll中定义。

namespace UserClasses
{
  public static class MyExtensions
  {
    public static List<Node> ConvertToCore(this re_Constituent node)
    {
      return new List<Node>()
      {
        new Node(); // actual code is more complex here
      };
    }
  }
}

该函数的代码可在另一个运行时加载的DLL中找到:

foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
    if(!assembly.GetName().Name.StartsWith("System"))
    foreach (Type type in assembly.GetTypes())
    {
        if(type.FullName.Name.StartsWith("System"))
            Console.WriteLine(type+":"+assembly.GetName().Name);
    }
}

通过迭代加载的所有程序集中的所有类,我注意到我的动态生成/加载有趣,这表明内存中有2个内置程序集的副本:

{{1}}

1 个答案:

答案 0 :(得分:1)

编译代码时,在加载类之前,这些类不可用于常规类型解析系统。解决此问题https://stackoverflow.com/a/3024112/432976 有编译结束的代码:

    AppDomain.CurrentDomain.Load(results.CompiledAssembly.GetName());
    return results.CompiledAssembly;

问题是从.Load调用返回的程序集读取与编译结果中已经存在内存的程序集不是同一个对象。

我的问题是我正在检查返回的程序集类型,并将它们缓存以备将来使用,这意味着我的re_constituent版本确实与类型系统知道的re_constituent的版本不同。

要解决此问题,请确保通过返回已加载的版本,只有一个程序集版本公开给用户代码:

 return AppDomain.CurrentDomain.Load(results.CompiledAssembly.GetName());