我正在使用Prism 4和MEF Extensions以及MVVM模式。在模块初始化期间,我调用RegisterViewWithRegion(RegionNames.MyRegion,typeof(MyView)),当视图构造如下时,它可以正常工作:
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class MyView : UserControl
{
public MyView()
{
....
视图已注册,一切正常。只要我将导出更改为自定义导出属性,就无法再找到视图,尽管它仍在容器中。此自定义导出属性取自Stock Trader RI:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
[MetadataAttribute]
public class ViewExportAttribute : ExportAttribute, IViewRegionRegistration
{
public ViewExportAttribute()
: base(typeof(object))
{ }
public ViewExportAttribute(string viewName)
: base(viewName, typeof(object))
{
ViewName = viewName;
}
public string RegionName { get; set; }
public string ViewName { get; set; }
}
,界面是
public interface IViewRegionRegistration
{
string RegionName { get; }
string ViewName { get; }
}
将导出属性更改为
[ViewExport(ViewName = "MyView", RegionName = RegionNames.MyRegion)]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class MyView : UserControl
{
public MyView()
{
....
调用RegisterViewWithRegion时会抛出错误:尝试获取MyView类型的实例时出现激活错误,键“”
有什么建议吗?我整天都在查看这部分代码而没有找到解决方案。
答案 0 :(得分:4)
另一天,另一种方式......即使我对PRISM知之甚少,我也会尝试回答我的问题。换句话说:我还在学习。
来自Stock Trade RI的自定义导出属性由AutoPopulateExportedViewsBehavior
使用。此行为通过检查区域名称的“导出属性”自动将视图添加到其区域,然后将视图添加到相应的区域。但是,使用此自定义属性的所有视图现在都具有合同名称“object”,这使得ServiveLocator无法找到它们。此自定义属性适用于具有固定区域/视图链接的方案。
使用自定义导出属性时的解决方案是获取“object”类型的所有导出以及相应的元数据:
MyView view;
var myList = container.GetExports<object, IViewRegionRegistration>();
foreach (Lazy<object, IViewRegionRegistration> lazy in myList)
{
if (lazy.Metadata.ViewName == "MyView")
{
view = lazy.Value as MyView;
region.Add(view);
break;
}
}
但我认为使用ViewInjection和Prism Navigation时最好只使用默认的[Export]属性,然后一切顺利。
答案 1 :(得分:4)
您是否在MEF引导程序中配置聚合目录?如果是这样,您是否添加包含ViewExportAttribute和AutoPopulateExportedViewsBehavior类的程序集?我相信这种情况发生在StockTraderRI的引导程序中:
this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(StockTraderRICommands).Assembly));
StockTraderRICommands类与ViewExportAttribute和AutoPopulateExportedViewsBehavior类位于同一个程序集中。
答案 2 :(得分:0)
自定义导出属性将typeof(object)
传递给基础构造函数,后者会更改导出的合同,使其不再与导入匹配。更改它,以便调用无参数构造函数。
就激活错误而言,您需要更详细地查看异常。根本原因可能在某处,可能埋藏在InnerException下。
答案 3 :(得分:0)
我遇到了完全相同的问题,对于MEF / PRISM初学者来说这是一个很难的问题。 okieh很好地描述了这个问题,我只想发布一个替代解决方案,来自 StocktraderUI示例应用程序:
如果您希望在没有任何形式的配置文件等的情况下查看发现,那么解决方案可以(/似乎可以工作),您必须注册视图。
<强> 1。修改ViewExport
自定义事件
[Export]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
[MetadataAttribute]
public sealed class ViewExportAttribute : ExportAttribute, IViewRegionRegistration
{
public ViewExportAttribute()
: base(typeof(UserControl))
{ }
public string ViewName { get { return base.ContractName; } }
public string RegionName { get; set; }
}
添加[Export]属性,现在使用UserControl
而不是object
调用基础构造函数。这样就可以被MEF发现。
<强> 2。修改AutoPopulateExportedViewsBehavior
[ImportMany(typeof(UserControl))]
public Lazy<UserControl, IViewRegionRegistration>[] RegisteredViews { get; set; }
添加[ImportMany]
属性,并将延迟初始化的类型更改为UserControl
。现在,导入所有UserControl
IViewRegionRegistration
- 实现MetaData类型。
基本上就是这样。您可以像以前一样使用[ViewExport]
。请注意,视图仅限于UserControl
的(子)类型。我想如果你愿意,可以修改。确保您的汇总目录导入ViewExportAttribute
和AutoPopulateExportedViewsBehavior
,正如Nicolaus所说......
这样,您不需要为视图添加其他界面,并且仍然可以在没有硬编码注册的情况下发现所有内容。
如果我错过了解决方案的任何缺点,我希望它有所帮助,让我知道。