This is a problem which is commonly solved using the Registry Pattern:
This is the situation that the
Registry Pattern describes:
Objects need to contact another
object, knowing only the object’s name
or the name of the service it
provides, but not how to contact it.
Provide a service that takes the name
of an object, service or role and
returns a remote proxy that
encapsulates the knowledge of how to
contact the named object.
It’s the same basic publish/find model
that forms the basis of a Service
Oriented Architecture (SOA) and for
the services layer in OSGi.
You implement a registry normally using a singleton object, the singleton object is informed at compile time or at startup time the names of the objects, and the way to construct them. Then you can use it to create the object on demand.
For example:
template<class T>
class Registry
{
typedef boost::function0<T *> Creator;
typedef std::map<std::string, Creator> Creators;
Creators _creators;
public:
void register(const std::string &className, const Creator &creator);
T *create(const std::string &className);
}
You register the names of the objects and the creation functions like so:
Registry<I> registry;
registry.register("MyClass", &MyClass::Creator);
std::auto_ptr<T> myT(registry.create("MyClass"));
We might then simplify this with clever macros to enable it to be done at compile time. ATL uses the Registry Pattern for CoClasses which can be created at runtime by name - the registration is as simple as using something like the following code:
OBJECT_ENTRY_AUTO(someClassID, SomeClassName);
This macro is placed in your header file somewhere, magic causes it to be registered with the singleton at the time the COM server is started.