【问题标题】:GetType(string) returns null after AppDomain.CurrentDomain.LoadGetType(string) 在 AppDomain.CurrentDomain.Load 之后返回 null
【发布时间】:2011-02-21 22:24:17
【问题描述】:

我正在构建一个小型插件架构(不幸的是,MEF 不是一个选项,因为它需要在 .NET 2.0 上运行)。 我希望能够将 dll 放在一个目录中,而无需重新编译主项目。 我的主要项目是一个 winforms 应用程序,它有一些对话框来选择主程序需要的接口的实现。

我有一个方法可以搜索某个目录并给出我想要搜索实现该接口的类型的 dll 的位置列表。

public List<Type> GetPluginTypes()
{
  List<Type> types = new List<Type>();
  foreach (string dll in this.Plugins)
  {
    Assembly assembly;
    try
    {
      assembly = AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(dll));
    }
    catch
    {
      continue;
    }
    foreach (Type type in assembly.GetExportedTypes())
    {
      if (type.IsInterface || type.IsAbstract)
        continue;

      if (typeof(IMyInterface).IsAssignableFrom(type))
       types.Add(type);
    }
  }
  return types;
}

使用这种方法,我向用户展示了一个实现列表,其中一个被选中,它的 AssemblyQualifiedName 被保存到一个设置文件中。

当我启动主应用程序时,我从设置中加载 AQN,并通过调用上述方法将所有插件加载到 AppDomain 中。

string typeName = GetSetting("MyPlugin");
GetPluginTypes(); // just to load the plugins into the app domain
Type.GetType(typeName); // allways returns null.

这是我的问题:Type.GetType(typeName),总是返回 null。

我使用 Type.GetType(typeName, true) 来强制执行异常,我得到了: 无法加载文件或程序集“MyImpl,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”或其依赖项之一。系统找不到指定的文件。":"MyImpl, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"}

我一无所知。我已经将程序集加载到AppDomain中,当我指定AQN时仍然找不到Type.GetType(string)。

【问题讨论】:

  • 在 types.Add(type) 之后我设置了一个断点并使用即时窗口进行调试:AppDomain.CurrentDomain.GetAssemblies(),其中列出了 MyImpl 程序集,向下钻取还显示了类组装
  • 另外,就在 types.Add(type) 之后,我调用了Type type2 = Type.GetType(type.AssemblyQualifiedName);,但 type2 也是 null。
  • FusionLog显示找不到MyImpl.dll本身。但是GetType为什么要搜索呢,已经加载好了!
  • 如果你已经有了你需要的类型的 Type 对象,为什么还要使用 GetType 按名称再次检索它?
  • @Lasse,因为该类型的程序集限定名称存储在配置文件中。下次程序运行时,我需要使用设置中的 AQN 获取 Type 对象。

标签: c# reflection interface gettype


【解决方案1】:

这可以通过为 AppDomain 注册 AppDomain.AssemblyResolve 事件来解决,该事件将请求程序集并使处理程序返回已加载的程序集。

这是处理程序在 C# 中的样子:

    private System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        return
            AppDomain.CurrentDomain.GetAssemblies()
            .FirstOrDefault(Kandidaat => string.Equals(Kandidaat.GetName().FullName, args.Name));
    }

详细的解释可以在这里找到: https://msdn.microsoft.com/en-us//library/ff527268(v=vs.110).aspx

【讨论】:

    【解决方案2】:

    也许这是相关的。来自Type.GetType(String, Boolean) 的文档:

    如果 typeName 仅包含 类型,此方法在 调用对象的程序集,然后在 mscorlib.dll 程序集。如果 typeName 是 完全合格的部分或 完整的程序集名称,此方法 在指定的程序集中搜索。

    您说您尝试使用type.AssemblyQualifiedName 拨打电话,但失败了。有没有检查限定名是否合理?

    【讨论】:

    • 我在调试时检查了所有内容,所以问题不是为什么找不到类型,而是为什么没有从已加载的程序集中获取程序集。 .NET 正在探测磁盘上的程序集 mscorlib 和正在执行的程序集,MyImpl 未找到,因为它位于单独的 Plugins 文件夹中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-11
    • 2021-03-18
    • 2016-05-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多