-
Notifications
You must be signed in to change notification settings - Fork 263
Initializing Components
If a component requires initialization, it should implement and export the IInitializable
interface. IInitializable
and the InitializeAll()
CompositionContainer
extension method are used to ensure that all components requiring initialization are created and initialized.
The IInitializable
interface contains the method Initialize()
.
As previously mentioned in Component Initialization, the CompositionContainer
extension method InitializeAll()
initializes components by calling their IInitializable.Initialize()
method. This performs initialization on the component that can't be put in the component's constructor. Many ATF components require such initialization.
A component must have been created for it to be initialized. However, MEF creates components lazily, that is, on an as needed basis. Using InitializeAll()
creates all the components so they can be initialized.
In ATF, any component that requires initialization implements IInitializable
and also decorates its class with this export:
[Export(typeof(IInitializable))]
For a few components, this is the only export decorator. Obviously, this decorator's purpose is not to export the IInitializable
interface, but is ATF's convention to mark components that need initialization. The next section explains the details of how initialization works.
The MefUtil
class implements the InitializeAll()
CompositionContainer
extension method. Examining this implementation reveals how the IInitializable
interface is used in ATF with MEF to initialize components that need it.
public static void InitializeAll(this CompositionContainer container)
{
if (container == null)
throw new ArgumentNullException("container");
// ImportDefinition
// - constraint: An expression that contains a Func<T, TResult> object that defines the conditions
// an Export must match to satisfy the ImportDefinition.
// - contractName: The contract name.
// - cardinality: One of the enumeration values that indicates the cardinality of the Export objects
// required by the ImportDefinition.
// - ImportCardinality.ZeroOrMore: Zero or more Export objects are required by the ImportDefinition.
// - isRecomposable: true to specify that the ImportDefinition can be satisfied multiple times
// throughout the lifetime of a ComposablePart object; otherwise, false.
// - isPrerequisite: true to specify that the ImportDefinition must be satisfied before a
// ComposablePart can start producing exported objects; otherwise, false.
var importDef = new ImportDefinition(contraint => true, string.Empty, ImportCardinality.ZeroOrMore, true, true);
try
{
// Create everything. This ensures that all objects are constructed before IInitializable
// is used. Note that the order of construction is not deterministic. We have seen the same
// code result in different orderings on different computers.
foreach (Export export in container.GetExports(importDef))
{
// Triggers creation of object (otherwise lazy).
// Also, IPartImportsSatisfiedNotification.OnImportsSatisfied() will be called here.
object tmp = export.Value;
}
// Initialize components that require it. Initialization often can't be done in the constructor,
// or even after imports have been satisfied by MEF, since we allow circular dependencies between
// components, via the System.Lazy class. IInitializable allows components to defer some operations
// until all MEF composition has been completed.
foreach (IInitializable initializable in container.GetExportedValues<IInitializable>())
initializable.Initialize();
}
catch (CompositionException ex)
{
foreach (var error in ex.Errors)
Outputs.WriteLine(OutputMessageType.Error, "MEF CompositionException: {0}", error.Description);
throw;
}
}
Analyzing this in detail, this line creates an ImportDefinition
object:
var importDef = new ImportDefinition(contraint => true, string.Empty, ImportCardinality.ZeroOrMore, true, true);
The first parameter returns true, so any Export satisfies this ImportDefinition
, which is then used in the following loop:
foreach (Export export in container.GetExports(importDef))
{
// Triggers creation of object (otherwise lazy).
// Also, IPartImportsSatisfiedNotification.OnImportsSatisfied() will be called here.
object tmp = export.Value;
}
GetExports()
gets all exports that match the conditions specified in importDef
, but this import imposed no conditions, so GetExports()
obtains all exports in the container. That is, every component in the MEF container that has an \Export\ attribute is obtained. The next line forces that component to be created. MEF creates objects lazily, so unless a component is imported, it might not be created otherwise.
Now that all components are created, the next lines perform any necessary initialization:
// Initialize components that require it. Initialization often can't be done in the constructor,
// or even after imports have been satisfied by MEF, since we allow circular dependencies between
// components, via the System.Lazy class. IInitializable allows components to defer some operations
// until all MEF composition has been completed.
foreach (IInitializable initializable in container.GetExportedValues<IInitializable>())
initializable.Initialize();
GetExportedValues<IInitializable>()
gets all the exported objects with the contract name derived from the specified type parameter, that is, all components that export IInitializable
. It then calls Initialize()
for each of these components.
In summary, if a component requires initialization, it should implement and export IInitializable
. Calling InitializeAll()
in the Main()
function that sets up the MEF catalog ensures that each component is initialized.
- What is MEF: Brief description of MEF with links to more detailed information.
- How MEF is Used in ATF: Examine how ATF is used in sample applications to compose components and how components are decorated.
- Initializing Components: How component initialization is implemented in ATF.
- Using ATF Components: How to use ATF components, discovering what you need to provide in your application.
- Creating MEF Components: How to create components of your own, using the attributes you need.
- Important ATF Components: Description of some key ATF components in functional areas as well as some components in sample applications.
- Finding ATF Components: How to find components you need for your application.
- Details on Selected ATF Components: Provides more details on some ATF components you might want to use in your applications.
- Details on Using Selected ATF Components: Shows exactly how to use certain components.
- Home
- Getting Started
- Features & Benefits
- Requirements & Dependencies
- Gallery
- Technology & Samples
- Adoption
- News
- Release Notes
- ATF Community
- Searching Documentation
- Using Documentation
- Videos
- Tutorials
- How To
- Programmer's Guide
- Reference
- Code Samples
- Documentation Files
© 2014-2015, Sony Computer Entertainment America LLC