Prism 4 Module Configuration management

Source: Internet
Author: User
Tags silverlight

Guide to this chapter:

The fourth chapter describes the module's life cycle in modular application development, the generation method, the survival time of the instance reference, and the 7 scenarios that are often applied to include the definition module (in unity as an example, it also illustrates the difference between MEF and unity in 4 points) and is implemented using code.

4.4 Core Scenarios

This section describes the scenarios that you might encounter in developing a modular application. These scenarios include defining modules, registering and discovering modules, loading modules, defining module dependencies, loading modules on demand, downloading modules in the background, and loading complete detections. You can register and discover modules in several ways through code, XAML, configuration files, and directory discovery.

4.4.1 Registration Module

Modules are packaged together in a logical collection of features and resources that can be independently developed, tested, deployed, integrated into the application. Each module has a hub class that is responsible for initializing and integrating functionality into the application. The class implements the IModule interface, as shown below.

protected override void Configuremodulecatalog ()
{
Type Modulectype = typeof (Modulec);
Modulecatalog.addmodule (
New Moduleinfo ()
{
ModuleName = Modulectype.name,
Moduletype = Modulectype.assemblyqualifiedname,
});
}
Copy Code

How you implement the Initialize method depends on the needs of your application. The types of modules, initialization methods, and module dependencies are defined in the list of modules. For each module in the list, the module loader creates an instance of the corresponding type and invokes the Initialize method in it. The modules are processed in the order in which they are defined in the list of modules. The initialization order of the runtime is based on when the module is downloaded, when the module needs to be used, and when the dependency of the module is satisfied.

Depending on the type of module list in your application, module dependencies can be set by the properties of the module itself or by a module list file. The following will be described in detail.

4.4.2 Registration and Discovery module

The modules that the application can load are defined in the module list. Prism Module Loader uses a list of modules to detect which modules are ready to be loaded into the application, when they are loaded, and in what order.

The list of modules is implemented by a class that inherits from Imodulecatagory . The list of modules is created by the initiator of the application when the application is created. Prism provides a variety of implementations of the module list to choose from. You can also port a list of modules from another data source by Addmodule the method or by creating a class that inherits from the modulecatagory and adds your own behavior.

"Note": Typically, the modules in prism use the dependency injection container and the common Service locator to retrieve an instance of the type that needs to be used in the initialization. Prism supports unity and MEF two frameworks. Although both frameworks are registered, found, downloaded, and initialized in the entire process, the details of the implementation are quite different. This article will explain some of the differences between containers.

4.4.3 registering a module in code

The Modulecatalog class is the most basic module list class. You can register modules in the module list as code by specifying the type of the module class. You can also specify the module name and initialization method in the form of code. The instance is shown below.

protected override void Configuremodulecatalog ()
{
Type Modulectype = typeof (Modulec);
Modulecatalog.addmodule (
New Moduleinfo ()
{
ModuleName = Modulectype.name,
Moduletype = Modulectype.assemblyqualifiedname,
});
}
Copy Code


In the example above, the module is referenced directly by the shell, so the type of the module class is already defined and can be called by the addmodule method. This is why the instance uses typeof (module) to add modules to the list of modules.

Note: If there is a direct reference between the application and the module type, you can add the module directly in the above method, or you will need to provide the full name of the module and the assembly in which it is located.

If you need more examples of defining modules in your code, you can view the StockTraderRIBootstrapper.cs files in the stock Trader Reference implementation (stock Trader RI).

Note: The base class Bootstrappper provides the createmodulecatagory method to help create the modulecatagory. By default, this method establishes an instance of modulecatagory . However, the method can be overridden by subclasses to create a list of other types of modules.

4.4.4 registering a module with a XAML file

You can define a declaration of a module list in a XAML file. This XAML file shows what type of module list is defined and which module is added: Typically, A. xaml file is added as a resource to the Shell project. The list of modules is created by the initiator by calling CreateFromXAML. From a technical point of view, this approach is very similar to defining modulecatagory in code, because XAML files simply define layers of objects that need to be instantiated.

The following code is a XAML file that describes the module list definition (code mode is XAML, taken from Modularitywithunity.silverlight\modulescatalog.xaml).

<modularity:modulecatalog xmlns= "Http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x= "Http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys= "Clr-namespace:system;assembly=mscorlib"
xmlns:modularity= "Clr-namespace:microsoft.practices.prism.modularity;assembly=microsoft.practices.prism" >
<modularity:moduleinfogroup ref= "moduleb.xap" initializationmode= "whenavailable" >
<modularity:moduleinfo modulename= "Moduleb" moduletype= "Moduleb.moduleb, Moduleb, Version=1.0.0.0, Culture= Neutral, publickeytoken=null "/>
</Modularity:ModuleInfoGroup>
<modularity:moduleinfogroup initializationmode= "OnDemand" >
<modularity:moduleinfo ref= "modulee.xap" modulename= "Modulee" moduletype= "Modulee.modulee, ModuleE, Version= 1.0.0.0, culture=neutral, Publickeytoken=null "/>
<modularity:moduleinfo ref= "modulef.xap" modulename= "Modulef" moduletype= "Modulef.modulef, ModuleF, Version= 1.0.0.0, Culture=neutral, Publickeytoken=null ">
<Modularity:ModuleInfo.DependsOn>
<sys:String>ModuleE</sys:String>
</Modularity:ModuleInfo.DependsOn>
</Modularity:ModuleInfo>
</Modularity:ModuleInfoGroup>

<!--Module Info without a group--
<modularity:moduleinfo ref= "moduled.xap" modulename= "moduled" moduletype= "moduled.moduled, ModuleD, Version= 1.0.0.0, culture=neutral, Publickeytoken=null "/>
</Modularity:ModuleCatalog>
Copy Code



Note: Moduleinfogroups provides an easy way to integrate in the same. xap file, or the same assembly, the same initialization method, or just a dependency between the two.

Dependencies between modules must be in the same moduleinfogroups ; In any case, you can't add a dependency to a module in two different moduleinfogroups .

Not all modules are placed in the moduleinfogroups . The properties that are designed in the group are applied to all the modules in it. Note that modules can be defined outside the list of modules.

In the application's Bootstrapper class, you need to specify the source of the XAML file definition for modulecatagory , as shown below.

protected override Imodulecatalog Createmodulecatalog ()
{
Return Modulecatalog.createfromxaml (The new Uri ("/myproject.silverlight;component/modulescatalog.xaml",
urikind.relative));
}
Copy Code

4.4.5 registering a list of modules in a configuration file

In WPF, you can specify a list of modules in the App. Config file. The benefit of this approach is that the file is not compiled into the application. Therefore, it is convenient to add or remove modules without recompiling the application.

The following code illustrates the use of a configuration file to define a module list. If you want the module to be loaded automatically, set startuploaded= "true".

Code format XML taken from modularitywithunity.desktop\app.config

  <modules>    
<module assemblyfile= "ModularityWithUnity.Desktop.ModuleE.dll" moduletype= " ModularityWithUnity.Desktop.ModuleE, ModularityWithUnity.Desktop.ModuleE, version=1.0.0.0, Culture=neutral, Publickeytoken=null "Modulename=" Modulee "startuploaded=" false "/>
<module assemblyfile= "ModularityWithUnity.Desktop.ModuleF.dll" moduletype= " ModularityWithUnity.Desktop.ModuleF, ModularityWithUnity.Desktop.ModuleF, version=1.0.0.0, Culture=neutral, Publickeytoken=null "Modulename=" Modulef "startuploaded=" false ">
<dependencies>
<dependency modulename= "Modulee"/>
</dependencies>
</module>
</modules>
Copy Code


Note:assemblyfile is still required even if the module's assembly is in the public assembly buffer or in the same directory as the application. This property is used to allow Imoduletypeloader to accurately map Moduletype.

In the Bootstrapper class of your application, you need to specify a definition source for the configuration file as modulecatagory . You need to use the Configurationmodulecatalog class to reach the target, as shown below.

protected override Imodulecatalog Createmodulecatalog ()
{
return new Configurationmodulecatalog ();
}
Copy Code

"Note": You can still add modules as code in Configurationmodulecatalog . You can use this method, for example, to ensure that the application can load the modules it absolutely needs to use.

Note: Silverlight cannot use the configuration file. If you need to use the configuration form in Silverlight, the recommended approach is to create a list of modules that belong to your own modulecatagory class to read from the server's Web service.

4.4.6 to discover modules from the file directory

The Directorymodulecatalog class in Prism allows you to specify a directory in WPF as a list of modules. This list of modules retrieves the specified directory and finds the assemblies used by the module in the application definition. In this way, you need to specify the module names for each module class and the dependencies they need to use. The following code is an instance of a list of modules that are built in the form of a specified directory discovery assembly.

protected override Imodulecatalog Createmodulecatalog ()
{
return new Directorymodulecatalog () {Modulepath = @ ". \modules"};
}
Copy Code


"Note": Silverlight does not support this feature. Because the Silverlight security module does not allow you to load an assembly from the file system.

4.4.7 Loading Module

After the modulecatagory is built, the module is ready to load and initialize. The loading of the module means that the module has been transferred from disk to memory. If the assembly does not exist on the local disk, the file must be obtained first. For example, the assembly is downloaded in the form of a Silverlight. xap file. The Modulemanager is responsible for coordinating the loading and initialization process.

4.4.8 Initialization Module

After the module is loaded, it is the turn to initialize. This means that the module class will create an instance and invoke its Initialize method. The initialization process is the integration of modules into the application. The initialization process for a module may be:

L Register the view with the application . If the module uses view injection or the view exploration participates in the UI composition, the view or view model must be associated with the appropriate view name. This allows the view to be displayed dynamically in the visual location of menus, toolbars, or other applications.

L Subscribe to application-level events or services . Typically, the application exposes the services and/or events that the module needs to use. Use the Initialize method to add module functionality to these application-level events and services.

For example, an application that shuts down may raise an event and the module wants to respond to this event. It is also possible that the module needs to provide some data to the application. For example, if you create a menuservice(which is responsible for adding or removing menu items), the Initialize method of this module is to add the correct menu items.

Note: The lifetime of the module instance is ephemeral by default. After the initialization process calls initalize , a reference to the module instance is freed. If you do not specify a strong reference to the module instance, it is recycled by the recycle mechanism.

This behavior is a possibility to subscribe to a problem with a weak reference event that has a pointer to a module, because your module has "disappeared" when the recycle occurred.

L Register the type with the dependency injection container . If you use a dependency injection pattern such as unity or MEF, the module needs to register the types that the application or other modules need to use. This can also be the type that is required to resolve a module to a container request.

4.4.9 Specifying module dependencies

Modules can be relied on with other modules. If module A is dependent on module B, module B must be initialized before module A. Modulemanager Tracks these dependencies and initializes the module based on them. Depending on how you create the module list, you can define the module dependencies in code, configuration files, or XAML.

4.4.9.1 defining dependencies in code

When registering a module in a WPF application through code definitions or directory excavations, Prism provides the declaration properties when the module is created. The code is shown below.

[Module (modulename = "Modulea")]
[Moduledependency ("moduled")]
public class Modulea:imodule
{
...
}
Copy Code

4.4.9.2 defining Dependencies in XAML

The following XAML illustrates that module F relies on module E.

<modularity:moduleinfo ref= "modulef.xap" modulename= "Modulef" moduletype= "Modulef.modulef, ModuleF, Version= 1.0.0.0, Culture=neutral, Publickeytoken=null ">
<Modularity:ModuleInfo.DependsOn>
<sys:String>ModuleE</sys:String>
</Modularity:ModuleInfo.DependsOn>
</Modularity:ModuleInfo>
Copy Code

4.4.9.3 defining dependencies in a configuration file

The following is an example of module d that is dependent on module B in App. Config.

<modules>
<module assemblyfile= "Modules/moduled.dll" moduletype= "moduled.moduled, moduled" moduleName= "ModuleD" >
<dependencies>
<dependency modulename= "Moduleb"/>
</dependencies>
</module>
Copy Code

4.4.10 loading modules on demand

To be able to load the module on demand, you need to specify initializationmode as OnDemandfor the module in the module list. You then need to write code in the application to request the module to load.

4.4.10.1 in code to load as needed

With properties, specify On-demand for the module, as shown below.

protected override void Configuremodulecatalog ()
{
Type Modulectype = typeof (Modulec);
This. Modulecatalog.addmodule (New Moduleinfo ()
{
ModuleName = Modulectype.name,
Moduletype = Modulectype.assemblyqualifiedname,
Initializationmode = Initializationmode.ondemand
});
Copy Code
4.4.10.2 in XAML specifies that loading as needed

In the list of defined modules in XAML, specify Initializationmode.ondemand, as shown below.

...
<modularity:moduleinfogroup initializationmode= "OnDemand" >
<modularity:moduleinfo ref= "modulee.xap" modulename= "Modulee" moduletype= "Modulee.modulee, ModuleE, Version= 1.0.0.0, culture=neutral, Publickeytoken=null "/>
...
Copy Code

4.4.10.3 specified as needed in the configuration file

In the list of modules defined in App. Config, specify initializationmode.ondemand, as shown below.

...
<module assemblyfile= "Modules/modulec.dll" moduletype= "Modulec.modulec, Modulec" moduleName= "ModuleC" Startuploaded= "false"/>
...
Copy Code

4.4.10.4 request loading of modules loaded on demand

When the module is specified to load on demand, the application can request the module to be loaded. The following code for the request module initialization requires a reference to the Imodulemanager service that the initiator registers with the container.

private void Onloadmodulecclick (object sender, RoutedEventArgs e)
{
Modulemanager.loadmodule ("Modulec");
}
Copy Code
4.4.11 Background Remote Download module

Downloading modules in the background after application startup, or only when they need to be used, will increase the speed at which the application is started.

4.4.11.1 Preparing the Download module

In a Silverlight application, the module is wrapped in a. xap file. In order to download separately from the application, you need to create a separate. xap file. You can choose to place multiple modules in a. xap file to balance the number of downloads and the size of each downloaded. xap file.

Note: For each. xap file, you will need to create a new Silverlight application project. In Visual Studio 2008 and 2010, only application projects produce a separate. xap file. But these projects do not require App.xaml or MAINPAGE.XAML.

4.4.11.2 Tracking Download Progress

The Modulemanager class provides an event that the application tracks the download progress of the module. It provides the bytes that have been downloaded and the total bytes and download percentages to download. With this data, you can display the download progress bar to the user.

This.moduleManager.ModuleDownloadProgressChanged + = this. modulemanager_moduledownloadprogresschanged;
Copy Code


Moduledownloadprogresschangedeventargs e)
{
...
}
Copy Code
4.4.12 Download Complete detection

The Modulemanager Service provides an event that the application detects that the module downloaded successfully or failed. You can get a reference to the service by relying on the injected Imodulemanager interface.

This.moduleManager.LoadModuleCompleted + = this. modulemanager_loadmodulecompleted;
Copy Code

void Modulemanager_loadmodulecompleted (object sender, Loadmodulecompletedeventargs e)
{
...
}
Copy Code


To ensure a loosely coupled relationship between the application and the module, the application should avoid using this event to integrate the module into the project. The correct approach is to use the Initialize method of the module to complete the integration.

Loadmodulecompletedeventargs contains the iserrorhandled property. If a module fails to load and the application does not want Modulemanager to log an error and throw an exception, you can set the property to true.

"Note": When a module is loaded and initialized, the corresponding assembly of the module cannot be uninstalled. and the reference to the module instance is not maintained by the Prism Library. Therefore, when the module class initialization is complete, the module instance may be recycled.

4.4.13 modules in the MEF

This section only highlights some of the differences when using MEF as a dependency injection framework.

"Note": When using MEF,Mefmodulemanager is called by Mefbootstrapper . It extends the Modulemanager and implements the IPartImportsSatisfiedNotification interface to ensure that when a new class is imported into the MEF Modulecatalog can be updated.

Registering modules with code in 4.4.13.1 MEF

When using MEF, the Moduleexport property is applied to the module class to enable MEF to automatically discover the class, as shown in the following code.

[Moduleexport (typeof (Moduleb))]
public class Moduleb:imodule
{
...
}
Copy Code

Using the Assemblycatalog class, you can also let MEF discover and load modules. This class is used to discover and import all modules in an assembly. With Aggregatecatalog, you can bind multiple lists to a logical list. By default, the mefbootstrapper of Prism creates an instance of Aggregatecatalog . You can register an assembly by overriding the Configureaggregatecatalog method, as shown in the code below.

protected override void Configureaggregatecatalog ()
{
Base. Configureaggregatecatalog ();
Module A is referenced in the project and directly in code.
This. AGGREGATECATALOG.CATALOGS.ADD (
New Assemblycatalog (typeof (Modulea). Assembly));

This. AGGREGATECATALOG.CATALOGS.ADD (
New Assemblycatalog (typeof (Modulec). Assembly));
}
Copy Code


The implementation of Mefbootstrapper in Prism guarantees the modulecatalog in aggregatecatalog and Prism in the MEF. synchronization, allowing Prism to add modules through modulecatalog or aggregatecatalog discovery.

"Note": MEF uses the lazy<t> extension to prevent instantiation caused by import and export before the Value property is used.

4.4.13.2 discovery of modules in the same directory in MEF

MEF provides a Directorycatalog to detect whether a directory contains modules in the assembly (or other types that MEF can import). In this case, you need to rewrite the configureaggregatecatalog method to register a directory. This method is only valid under WPF.

Before using this method, you first need to use the Moduleexport property to define the name and dependency of the module, as in the code described below. This will allow MEF to import the module and let Prism update Modulecatalog.

protected override void Configureaggregatecatalog ()
{
Base. Configureaggregatecatalog ();

Directorycatalog Catalog = new Directorycatalog ("Directorymodules");
This. AGGREGATECATALOG.CATALOGS.ADD (catalog);
}
Copy Code

4.4.13.3 specifying dependencies in the MEF

Using MEF in a WPF program, use the Moduleexport property as shown below.

[Moduleexport (typeof (Modulea), dependsonmodulenames = new string[] {"moduled"})]
public class Modulea:imodule
{
...
}
Copy Code

Because MEF allows modules to be discovered at run time, it means that dependencies between modules can be added at run time. Even if you use modulecatalogin MEF, keep in mind that Modulecatalog determines the dependency chain when it is loaded from XAML or configuration files (before the other modules are loaded). When the module is listed in Modulecatalog and is loaded by MEF, the dependency inModulecatalog is used, and the dependsonmodulenames attribute is ignored. Using modulecatalog To configure MEF is typically used in Silverlight because it encapsulates modules into multiple XAP files.

4.4.13.4 specifying on-demand loading in MEF

If you use MEF, and you specify dependencies between modules and modules through the Moduleexport property, you can use the Initializationmode property to specify whether a module is loaded on demand, as shown below.

[Moduleexport (typeof (Modulec), Initializationmode = Initializationmode.ondemand)]
public class Modulec:imodule
{
}
Copy Code
4.4.13.5 preparing remote downloads for modules in MEF

Under the engine, use the MEF's Deploymentcatalog class to download the. xap file using the MEF's Prism application and discover the assemblies and types contained in these. xap files. Mefxapmoduletypeloader adds each deploymentcatalog to the aggregatecatalog .

If you download two different. xap files and contain the same shared assembly, the same type is imported again. This throws a build error when a class needs to keep a singleton, and it makes the assembly it is an assembly that is shared between modules. The Microsoft.Practices.Prism.MefExtensions.dll is one such assembly.

To prevent multiple imports, open each of the module project references and set the shared DLL as ' Copy Local ' =false. These will prevent these files from being copied to the module's XAP file and referenced two times. This also reduces the size of the entire application. Of course you also need to make sure that before the module is downloaded, the application references these shared assemblies or the application downloads a xap file that contains those assemblies.

Prism 4 Module Configuration management

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.