如何在Prism / Composite Application Library中动态加载模块?

时间:2009-09-14 09:34:15

标签: c# wpf dependency-injection unity-container prism

我的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

这是一个基于zipcode验证的简单文本框控件,但是开发人员可以创建另一个控件:

ZipCodePlus.dll

继承了相同的界面,但为zipcodes提供了弹出的地理选择器。一旦客户将 ZipCode.dll 替换为 ZipCodePlus.dll ,他的所有表单都会有 功能用于搜索邮政编码。

但是,我无法直观地了解这将如何在技术上实现,因为我的表单类正在解析XML,它实例化了为控件提供功能的类,但为了实例化班级,我必须有一个参考

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

但是我如何实例化动态,即将类的名称作为字符串,如果该类不存在则会抛出一个合适的异常,例如像这样的东西:

伪码:

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

1 个答案:

答案 0 :(得分:3)

您似乎非常接近解决问题的技术方案。我只想创建一个接口 - 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。这听起来像一个有趣的想法......我很想知道你如何继续实施。您甚至可以更进一步,根据ASP.NET MVC中的一些概念创建一个完整的XAML构建器框架。它可以方便测试,但具有WPF的强大功能。祝你好运!

相关问题