当使用MEF时,Type.GetType返回null。

3

我目前正在使用MEF导入插件的一个项目,由于插件是用WPF编写的,每个插件都有一个视图和一个视图模型。插件知道视图模型,但主壳体UI将使用一种约定优于配置类型的模式构建视图并绑定视图模型。

我使用了Build-your-own-MVVM-framework示例中的一些代码来进行自动视图发现:

    [ImportMany(typeof(IPlugin))]
    public IEnumerable<IPlugin> Plugins { get; set; }

   var viewTypeName = this.Plugins.First().ViewModel.GetType().AssemblyQualifiedName.Replace("Model", string.Empty);
   var viewType = Type.GetType(viewTypeName,true);

目前的代码只获取第一个插件并从名称中取出Model,返回视图名称并获取视图类型,以便我可以构建它。因此,viewType的示例可能是:

PluginTest.TestView, PluginTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

然而,当我调用Type.GetType(viewType)时,返回的是null。如果我添加true参数来抛出异常,我会得到以下异常:

Could not load file or assembly 'PluginTest, Version=1.0.0.0, Culture=neutral, 
PublicKeyToken=null' or one of its dependencies. 
The system cannot find the file specified.

即使已经使用MEF加载,但如果我执行以下操作:
var types = Assembly.GetAssembly(this.Plugins.First().ViewModel.GetType()).GetTypes();

我得到了插件程序集中所有类型的列表,目前只有PluginTest.TestViewPluginTest.TestViewModel
有人能帮我解决这个问题吗?
编辑:抱歉之前没有提到,插件与我的主壳体应用程序在不同的程序集中。
3个回答

4

可能最简单的方法是这样做:

var modelType = this.Plugins.First().ViewModel.GetType();
var viewTypeName = modelType.FullName.Replace("Model", string.Empty);
var viewType = modelType.Assembly.GetType(viewTypeName);

我不确定为什么 Type.GetType 对你不起作用 - 程序集解析是一个棘手的问题 - 但如果你知道类型应该在哪个程序集中定义,我强烈建议使用 Assembly.GetType


@Nathan:当你尝试上述代码时,viewTypeName是什么? - Jon Skeet
啊,不好意思,它可以工作了 :) 你一直在那里使用modelType.FullName吗?我发誓我之前用的是modelType.Name,所以我的代码没能正常工作。谢谢。 - Nathan W
@Nathan:我曾经很短暂地使用了 Name,但是在发布后的30秒内就进行了编辑... - Jon Skeet
我刚才按下了Ctrl+C太快了,不过没关系,现在它完美地运作了。 - Nathan W

1

0
这个问题早已得到解答,但以防万一有人碰巧遇到了同样的问题,这里是我的解决方案。
正如其他答案所指出的那样,问题在于尽管程序集已经通过MEF加载,但一旦使用GetType(),它就会再次被加载。不幸的是,我无法控制调用GetType()的代码,因此Jon Skeet的解决方案在我的情况下行不通。
在我的情况下,可以通过将插件程序集的位置添加到应用程序的探测路径中来解决问题。
另一种解决方案(这也是我最终采取的方案)是实现AssemblyResolve事件,并手动加载程序集。与探测路径解决方案相比,这种解决方案非常灵活,如果事先不知道插件的安装目录,它也可以工作。

另外:如果您的插件有任何依赖程序集,您必须使用这两个解决方案之一,否则在首次使用这些依赖项时会出现FileNotFound异常。


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