ПРИЗМА 4 - RegisterViewWithRegion и пользовательские атрибуты экспорта - PullRequest
5 голосов
/ 08 июня 2011

Я использую Prism 4 с расширениями MEF и шаблоном MVVM.Во время инициализации в модуле я вызываю RegisterViewWithRegion (RegionNames.MyRegion, typeof (MyView)), который отлично работает, когда представление построено так:

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

Представление регистрируется и все в порядке.Как только я изменю Экспорт на пользовательский атрибут экспорта, представление больше не будет найдено, хотя оно все еще находится в контейнере.Этот пользовательский атрибут экспорта взят из RI Stock Trader:

[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, ключ ""

Любой совет?Я весь день искал эту часть кода, не найдя решения.

Ответы [ 4 ]

4 голосов
/ 08 июня 2011

В другой день, по-другому ... Я постараюсь ответить на мой вопрос, хотя у меня есть только ограниченные знания о ПРИЗМЕ.Другими словами: я все еще учусь.

Пользовательский атрибут экспорта, взятый из RI Stock Trade, используется AutoPopulateExportedViewsBehavior.Это поведение добавляет представление в свой регион автоматически, проверяя атрибут экспорта для имени региона, а затем добавляет представление в соответствующий регион.Но все представления с этим пользовательским атрибутом теперь имеют контрактное имя «объект», что делает невозможным их поиск в 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 лучше просто использовать значения по умолчанию[Экспорт], то все работает без сбоев.

4 голосов
/ 19 октября 2011

Вы настраиваете каталог агрегатов в загрузчике MEF? Если да, добавляете ли вы сборку, содержащую ваши классы ViewExportAttribute и AutoPopulateExportedViewsBehavior? Я полагаю, что это происходит в загрузчике StockTraderRI со следующей строкой:

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

Класс StockTraderRICommands находится в той же сборке, что и классы ViewExportAttribute и AutoPopulateExportedViewsBehavior.

0 голосов
/ 26 ноября 2012

Я столкнулся с точно такой же проблемой, и она была трудной для начинающего 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.Теперь все UserControl s с IViewRegionRegistration -производящим MetaData-type импортируются.

Вот и все.Вы можете использовать [ViewExport], как и раньше.Обратите внимание, что представления ограничены (под) типами UserControl.Я полагаю, это можно изменить, если вы хотите.И убедитесь, что ваш сводный каталог импортирует ViewExportAttribute и AutoPopulateExportedViewsBehavior, как сказал Николаус ...

Таким образом, вам не нужны дополнительные интерфейсы для ваших представлений, и вы все равно можете обнаружить все без жестко прописанной регистрации.

Надеюсь, это поможет и даст мне знать, если я пропустил какие-либо недостатки моего решения.

0 голосов
/ 08 июня 2011

Пользовательский атрибут экспорта передает typeof(object) в базовый конструктор, который изменяет экспортируемый контракт, чтобы он больше не соответствовал импорту. Измените его так, чтобы он вызывал конструктор без параметров.

Что касается ошибки активации, вам нужно рассмотреть исключение более подробно. Основная причина, вероятно, где-то там, возможно, скрыта под InnerException.

...