Как да заредите динамично модули в Prism / Composite Application Library?

Имам клас в моето приложение 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 ще съществува в директория Modules като файл:

ZipCode.dll

което е просто просто текстово поле контрола, която валидира въз основа на пощенски код, но разработчиците могат да направят друга контрола, наречена:

ZipCodePlus.dll

който наследява същия интерфейс, но предоставя изскачащ гео-земен селектор за пощенски кодове. Веднага след като клиент замени ZipCode.dll с ZipCodePlus.dll, всички негови формуляри ще имат тази нова функционалност за търсене на пощенски кодове.

Имам обаче проблеми с визуализирането на това как това ще бъде технически изпълнено, тъй като тъй като класът ми на формуляр анализира XML, той инстанцира класовете, които предоставят функционалността за контролите, но за да инстанцира клас, трябва да имам препратка към него:

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