Как динамически загружать модули в библиотеку приложений Prism / Composite?

У меня есть класс в моем приложении Prism / CAL, который генерирует форму для пользователей для ввода данных.

Форма определяется файлом XML следующим образом:

<area idCode="general" title="General">
    <column>
        <group title="Customer Data">
            <field idCode="title" requiredStatus="true">
                <label>title</label>
                <fieldType>Title</fieldType>
            </field>
            <field idCode="firstName" requiredStatus="true">
                <label>First Name</label>
                <fieldType>Text</fieldType>
            </field>
            <field idCode="lastName" requiredStatus="true">
                <label>Last Name</label>
                <fieldType>Text</fieldType>
            </field>
            <field idCode="email" requiredStatus="true">
                <label>E-Mail</label>
                <fieldType>Email</fieldType>
            </field>
            ...
        </group>
        </column>
    </area>

форма должна загружать определенные элементы управления, соответствующие каждому типу поля в XML, например

  • Название (показывает раскрывающийся список: мистер, миссис, доктор и т. д.)
  • Текст (простое текстовое поле)
  • Электронная почта (текстовое поле с подтверждением электронной почты)
  • ZipCode (текстовое поле с проверкой почтового индекса)

Я хочу сделать каждый элемент управления отдельным модулем, который загружается, например, модуль ZipCode будет существовать в каталоге Modules в виде файла:

ZipCode.dll

это просто элемент управления простое текстовое поле, которое проверяется на основе почтового индекса, но разработчики могут создать другой элемент управления с именем:

ZipCodePlus.dll

который наследует тот же интерфейс, но предоставляет всплывающий селектор геолокации для почтовых индексов. Как только клиент заменит ZipCode.dll на ZipCodePlus.dll, все его формы будут иметь эту новую функциональность для поиска почтовых индексов.

Однако у меня возникли проблемы с визуализацией того, как это будет технически реализовано, поскольку, поскольку мой класс формы анализирует XML, он создает экземпляры классов, которые предоставляют функциональные возможности для элементов управления, но для того, чтобы создать экземпляр class, у меня должна быть ссылка на него:

SmartFormFieldZipCodePresenter smartFormFieldEmailPresenter
    = container.Resolve<SmartFormFieldEmailPresenter>();

Но как я могу создать его динамически, то есть с именем класса в виде строки, и если этот класс не существует, он выдаст соответствующее исключение , например что-то вроде этого:

ПСЕВДОКОД:

try {
    var smartFormFieldZipCodePresenter
        = container.Resolve("smartFormFieldZipCodePresenter");
}
catch (ModuleDoesNotExistException) {
    ...
}

person Edward Tanguay    schedule 14.09.2009    source источник
comment
Какой парсер вы используете. это ленивая загрузка или жадная загрузка. Мы также используем похожий подход.   -  person Mohanavel    schedule 11.01.2011


Ответы (1)


Похоже, вы очень близки к техническому решению вашей проблемы. Я бы просто создал интерфейс - IZipCodePresenter - и при запуске модуля ZipCode.dll или ZipCodePlus.dll зарегистрировал реализацию.

Container.RegisterType<IZipCodePresenter, StandardZipCodePresenter>();

Затем в вашем парсере разрешите экземпляр, например:

var zipCodePresenter = container.Resolve<IZipCodePresenter>();

Если для интерфейса не зарегистрировано ни одного экземпляра, будет выдано исключение. В противном случае вы получите последнюю зарегистрированную конкретную реализацию IZipCodePresenter. Обратите внимание, что исключение будет выдано только в том случае, если вы попытаетесь зарегистрировать интерфейс. Если вы попытаетесь зарегистрировать класс в Unity, он создаст экземпляр на основе политики Lifetime Manager.

Если вы хотите пойти дальше, вы можете создать интерфейс ... что-то вроде IDynamicPresenter. Затем вы можете зарегистрироваться на основе известной строки (определенной в вашем инфраструктурном проекте).

Container.RegisterType<IDynamicPresenter, StandardZipCodePresenter>(PresenterName.ZipCodeControl);
Container.RegisterType<IDynamicPresenter, StandardEmailPresenter>(PresenterName.EmailControl);

а затем решите следующим образом:

var zipCodeControl = Container.Resolve<IDynamicPresenter>(PresenterName.ZipCodeControl);
var emailControl = Container.Resolve<IDynamicPresenter>(PresenterName.EmailControl);

Я предпочитаю первое решение, но это, безусловно, допустимый вариант.

Надеюсь это поможет!

P.s. Звучит как интересная идея ... Мне было бы интересно услышать, как вы продвигаетесь с реализацией. Вы даже можете сделать еще один шаг и создать целую платформу построителя XAML на основе некоторых концепций ASP.NET MVC. Это может облегчить тестирование, но при этом обладает мощью WPF. Удачи!

person Brad Leach    schedule 14.09.2009