PRISM 4 - RegisterViewWithRegion & Custom Export Attributes



我正在使用带有MEF扩展和MVVM模式的Prism 4。在模块初始化期间,我调用RegisterViewWithRegion(RegionNames.MyRegion,typeof(MyView)),当视图构造为这样时,它可以完美地工作:

[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class MyView : UserControl
{
    public MyView()
    {
     ....

视图已注册,一切正常。一旦我将"导出"更改为"自定义导出属性",就再也找不到视图了,尽管它仍在容器中。此自定义导出属性取自股票交易员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的实例时发生激活错误,密钥为"

有什么建议吗?我整天都在看这部分代码,却没有找到解决方案。

又是一天,又是另一种方式。。。尽管我对PRISM的了解有限,但我会尽力回答我的问题。换句话说:我还在学习。

AutoPopulateExportedViewsBehavior使用从股票交易RI获取的自定义导出属性。此行为通过检查区域名称的"导出属性"(Export Attribute),自动将视图添加到其区域,然后将视图添加至相应的区域。但是,所有具有此自定义属性的视图现在都有一个约定名称"object",这使得ServiveLocator无法找到它们。此自定义属性适用于具有固定区域/视图链接的场景。使用自定义导出属性时的解决方案是获取"对象"类型的所有导出和适当的元数据:

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]属性,这样一切都会顺利进行。

您是否在MEF引导程序中配置聚合目录?如果是,您是否正在添加包含ViewExportAttribute和AutoPopulateExportedViewsBehavior类的程序集?我相信这发生在StockTraderRI的引导程序中,它有这样一行:

this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(StockTraderRICommands).Assembly));

StockTraderRICommands类与ViewExportAttribute和AutoPopulateExportedViewsBehavior类位于同一程序集中。

自定义导出属性将typeof(object)传递给基构造函数,该构造函数将更改导出的协定,使其不再与导入匹配。将其更改为调用无参数构造函数。

至于激活错误,您需要更详细地查看异常。根本原因可能在某个地方,可能埋在InnerException之下。

我遇到了完全相同的问题,对于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]属性,并且Lazy初始化的类型更改为UserControl。现在,所有具有IViewRegionRegistration实现元数据类型的UserControl都已导入。

基本上就是这样。你可以像以前一样使用[ViewExport]。请注意,视图仅限于UserControl的(子)类型。如果你愿意的话,我想这可以修改。并确保你的聚合目录导入ViewExportAttributeAutoPopulateExportedViewsBehavior,正如Nicolaus所说。。。

这样,您就不需要为视图提供额外的接口,并且仍然可以在没有硬编码注册的情况下发现所有内容。

如果我错过了解决方案的任何缺点,我希望它能帮助我,并让我知道。

相关内容

  • 没有找到相关文章