我目前正在使用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.TestView
和PluginTest.TestViewModel
任何人都可以帮我这个吗?
编辑:很抱歉之前没有提到,插件与我的主shell应用程序位于不同的程序集中。
答案 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上下文中加载它们。
答案 2 :(得分:0)
这个问题早已得到解答,但万一有人偶然发现,这是我的解决方案。
正如其他答案所指出的那样,问题是虽然程序集已通过MEF加载,但一旦使用GetType()
,它就会再次加载。不幸的是,我无法控制调用GetType()
的代码,因此Jon Skeet的解决方案在我的情况下不起作用。
在我的情况下,可以通过将插件程序集的位置添加到应用程序的probing path来解决问题。
另一种解决方案(我最终做的)是实现AssemblyResolve
事件,并手动加载程序集。这个解决方案非常灵活,与探测路径解决方案相反,如果您事先不知道插件的安装目录,它也可以工作。
另外:如果您的插件有任何依赖程序集,则必须使用这两种解决方案中的一种,否则在首次使用这些依赖项时会出现FileNotFound异常。