Autowiring
1.0.3
A C++ Inversion of Control Framework
|
Contexts are the base container and scope mechanism of autowiring. The context determines how autowired dependencies are resolved, how events are broadcast, the scope of filter graph networks, and the lifetime of threads.
Every application has a global context, which is created automatically. You can also create additional contexts as needed. Contexts are created in a tree structure with the global context at its root.
If you do nothing else, every autowiring operation takes place within the global context. There is always a single current context. When you start the application, the global context is current. You can change the current context as needed.
To get a reference to the global context, use:
AutoGlobalContext global;
Avoid holding this reference longer than necessary.
Get a reference to the current context with:
AutoCurrentContext current;
You can use the ContextEnumerator and ContextEnumeratorT classes to enumerate existing contexts.
The simplest way to create a new context is with:
AutoCreateContext newContext;
This creates a new context as a child of the current context. You can also create a context as a child of another context with the CoreContext::Create() and CoreContext::CreatePeer() methods.
You can categorize your contexts by assigning a sigil class at creation. A sigil class serves as a marker, which you can use to identify contexts by type. The sigil class can be any type, even an empty class declaration. Use the AutoCreateContextT template to create a class with a sigil:
class Foo{}; AutoCreateContextT<Foo> contextWithSigil;
You can check the sigil of a context with CoreContext::GetSigilType(). (Use the autowiring::demangle() function to get a human-readable string from the std::type_info object.) You can also enumerate contexts that share a given sigil using ContextEnumeratorT. The sigil class used for the global context is GlobalCoreContext.
All basic autowiring operations take place in the current context. You can change contexts in a number of ways:
AutoCreateContext foo; foo->SetCurrent();
{ //limits scope CurrentContextPusher push(ctxt); //Saves the current context before swithing to ctxt // ... perform some actions } // push goes out of scope, restoring previous context
The easiest way to enumerate contexts is with the ContextEnumerator classes. ContextEnumerator enumerates all children of a specified context. CurrentContextEnumerator is a special case that enumerates the current context. When enumerating, the parent context is included. ContextEnumeratorT enumerates only those children created with a specific sigil class. The parent context is included in the enumeration is it has the matching sigil.
To enumerate all contexts:
If you use the CurrentContextPusher class to change to the enumerated context, the current context is restored automatically when the for-loop terminates.
Similarly, to enumerate all contexts with the sigil class, Foo:
Alternately, you can enumerate contexts manually with the CoreContext functions like CoreContext::firstChild() and CoreContext::nextSibling();
The Autowiring library provides a few classes for adding objects to a context and connecting resources to the requested resources.
When you autowire a type, the autowiring system looks for an existing instance of that type and assigns a shared pointer to the existing instance, if one exists. Dependencies wired to a child context can be satisfied by resources in parent (or other direct ancestor) context, but not by one in a peer or sub-child context.
The primary ways to autowire a dependency to a context include:
Only one instance of a type can be autowired to a context. All slots created for the same type will be filled with a shared pointer to the same instance.
The type specified in an autowiring declaration does not need to be a concrete type. If you autowire (but nor auto-require) a pure abstract type, for example, the dependency can be resolved by any concrete implementation of that type. However, if more than one concrete type already exists in a context, autowiring a common super type leads to an exception. Attempting to use AutoRequired for a type that cannot be constructed also leads to an exception.