Using ATF Components - kaisu1986/ATF GitHub Wiki

Table of Contents

This section discusses what you need to do to use ATF components.

Add Components to Catalog

As shown in Creating a Catalog, you add the components you want to a MEF catalog in your Main() function.

You also need to add using statements for the namespaces of whatever components you use, or fully qualify the component names in the catalog.

For guidance in choosing components, see Important ATF Components and Finding ATF Components.

Set Up MEF Infrastructure

The section MEF Composing shows how most ATF samples provide the code that MEF requires. You can adapt this to your own application.

Note that if you are using any component that requires initialization that its constructor can't do, you must call the InitializeAll() extension method of CompositionContainer.

Satisfy Component Requirements

Most components are not self-contained and require something additional to work properly.

For some components, you need to do very little. You can simply add other components to your MEF catalog. For instance, the StandardFileExitCommand component adds the File > Exit menu item that exits the application. It requires the CommandService component, which handles commands in menus and toolbars. If you include StandardFileExitCommand but leave CommandService out of your catalog, the File > Exit menu item does not appear. In fact, your application would have no menus at all (unless you added them some other way). If a component requires other components in order to function properly, this is generally noted in the component�s documentation.

Other components require the application to provide some functionality. For example, the StandardFileCommands component adds standard File menu commands for New, Open, Save, SaveAs, and Close. The application, in turn, must provide its own component containing code to handle these file commands: processing opened file data, displaying it, and so on. In other words, the application performs its own specialized functions for each menu command.

Discovering What's Required

To see what is needed by a component to function, look at its Import attributes. As mentioned, a component may require other components or require some functionality from the application itself.

If any ATF samples use a component of interest, any other components needed by that component are listed in the sample's MEF catalog.

Functionality Required From Other Components

Consider what StandardFileExitCommand needs by looking at its Imports. StandardFileExitCommand.cs contains three:

[ImportingConstructor]
public StandardFileExitCommand(ICommandService commandService)
...
[Import(AllowDefault = true)]
private IMainWindow m_mainWindow;

[Import(AllowDefault = true)]
private Form m_mainForm;

The latter two imports are common in components that work with a UI: a System.Windows.Forms.Form for a WinForm application, and a Sce.Atf.Applications.IMainWindow. IMainWindow abstracts the idea of a main window for the application and allows components to work with WinForms, WPF, and other UI toolkits. The Main() function in Program.cs creates a MainForm (derived from Form), which satisfies these two import requirements.

The parameter for the constructor decorated with [[ImportingConstructor]] indicates the component also imports ICommandService. In turn, the ATF component CommandService exports ICommandService:

[Export(typeof(ICommandService))]
[Export(typeof(IInitializable))]
[Export(typeof(CommandService))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class CommandService : CommandServiceBase

Adding the CommandService component satisfies StandardFileExitCommand's needs, so CommandService should be included in the MEF catalog whenever StandardFileExitCommand is.

Note that you can also satisfy this import by creating and adding your own component that exports ICommandService.

Functionality Required in Application

Now consider the StandardFileCommands component, which adds standard File menu commands. It stands to reason that this component would require support from the application, since these commands are clearly application-dependent. What exactly is required?

Here are StandardFileCommands's imports:

[ImportingConstructor]
public StandardFileCommands(
    ICommandService commandService,
    IDocumentRegistry documentRegistry,
    IFileDialogService fileDialogService)
...
[Import(AllowDefault = true)]
private IStatusService m_statusService;

[ImportMany]
private Lazy<IDocumentClient>[] m_documentClients;

The constructor associated with the [[ImportingConstructor]] has three parameters. This import is very similar to the one for StandardFileExitCommand. It indicates components are required that export ICommandService, IDocumentRegistry, and IFileDialogService. These exports can be supplied by the ATF components CommandService, DocumentRegistry, and FileDialogService.

Similarly, the second import indicates that a component supplying IStatusService is needed, which is exported by the ATF component StatusService.

The last import indicates something the application itself must supply: something that exports IDocumentClient. This makes sense, because the IDocumentClient interface contains methods to support File commands, such as CanOpen() and Open() for the Open command. For example, the ATF Simple DOM Editor Sample uses StandardFileCommands and provides an Editor component that both exports and implements the IDocumentClient interface. Examining this sample shows that it also includes the ATF components listed above in its MEF catalog to meet the other import requirements.

There are two other things to note about the IDocumentClient import:

  • An array is imported into and the attribute [[ImportMany]] is used. This allows an application to provide several implementations of IDocumentClient in case it handles multiple document types.
  • It uses Lazy<T> for lazy initialization of components providing the IDocumentClient implementation. Such components might be large, and especially if there is more than one, all components might not be needed during an application's lifetime. Creating the components as needed improves the application's performance and resource usage.

Topics in this section

⚠️ **GitHub.com Fallback** ⚠️