【问题标题】:dynamic invoke throws error "Object of type 'myObject' can not be converted to type 'myObject' "动态调用抛出错误“'myObject'类型的对象无法转换为'myObject'类型”
【发布时间】:2017-11-15 10:02:11
【问题描述】:

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

invoke 调用异常: {System.ArgumentException:“UserClasses.re_Constituent”类型的对象无法转换为“UserClasses.re_Constituent”类型。}

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

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

有人知道错误的来源吗?


magicValue Invoke() 处的以下代码异常

namespace myTest
{
  internal class Program
  {
    Main(){
      //pseudoCode
        BuildTypes();
        {Type myType,MethodInfo myMethod} = factory.getType("re_Constituent");

      //actual code that exceptions
        Node result = (Node) JSON.Deserialize(textstream,myType);
        object magicValue = myMethodInfo.Invoke(null,new object[]{result});
    }
}
namespace UserClasses
{
  public abstract class Node
  {}
}

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

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 class re_Constituent : Node
  {
    public string id;
    ... other fields
  }
}

函数的代码在另一个运行时加载的 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
      };
    }
  }
}

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

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);
    }
}

【问题讨论】:

    标签: c# reflection


    【解决方案1】:

    当您编译代码时,在加载类之前,一般类型解析系统无法使用这些类。解决这个问题https://stackoverflow.com/a/3024112/432976 有编译结束的代码:

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

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

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

    要解决此问题,请通过返回 Loaded 版本确保只有 1 个程序集版本暴露给用户代码:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-17
      • 2021-08-06
      • 2010-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多