Using ATF Components - kaisu1986/ATF GitHub Wiki
This section discusses what you need to do to use ATF components.
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.
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
.
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.
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.
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
.
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 ofIDocumentClient
in case it handles multiple document types. - It uses
Lazy<T>
for lazy initialization of components providing theIDocumentClient
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.