使用MEF时,Type.GetType返回null

时间:2010-06-29 05:49:54

标签: c# wpf mvvm types mef

我目前正在使用MEF来导入插件,因为插件是用WPF编写的,每个插件都有一个视图和一个viewmodel。插件知道viewmodel,但主shell UI将构造视图并使用约定优于配置类型模式绑定viewmodel。

我使用了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

任何人都可以帮我这个吗?

编辑:很抱歉之前没有提到,插件与我的主shell应用程序位于不同的程序集中。

3 个答案:

答案 0 :(得分:4)

最简单的做法是这样:

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

我不确定为什么Type.GetType不适合你 - 装配解决方案是一个棘手的野兽 - 但如果你知道装配的类型应该以任何方式定义,我肯定会通过{{ 1}}而不是。

答案 1 :(得分:1)

程序集可能已加载到Load-From上下文和Type.GetType() doesn't work with assemblies loaded in that context。 MEF尝试在默认上下文中加载程序集,但如果这不起作用,则会在Load-From上下文中加载它们。

More about assembly load contexts in .NET

答案 2 :(得分:0)

这个问题早已得到解答,但万一有人偶然发现,这是我的解决方案。

正如其他答案所指出的那样,问题是虽然程序集已通过MEF加载,但一旦使用GetType(),它就会再次加载。不幸的是,我无法控制调用GetType()的代码,因此Jon Skeet的解决方案在我的情况下不起作用。

在我的情况下,可以通过将插件程序集的位置添加到应用程序的probing path来解决问题。

另一种解决方案(我最终做的)是实现AssemblyResolve事件,并手动加载程序集。这个解决方案非常灵活,与探测路径解决方案相反,如果您事先不知道插件的安装目录,它也可以工作。

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

相关问题