3

I have an ESB. Any serialized message transports its own fully qualified name (that is, namespace + class name). I have a concrete type for each message that encapsulates a specific logic to be executed.
Every time I receive a message, I need to deserialize it at first, so I can perform its operations --once more, depending on its concrete type--.

I need a way to register every single class at compile time or during my application initialization.
With .net I would use reflection to scan assemblies and discover the message types during initialization, but how would you do it in C++?

Jørgen R
  • 10,568
  • 7
  • 42
  • 59
mister why
  • 1,967
  • 11
  • 33

3 Answers3

3

C++ has no reflection capability. I suppose you could try to scan object files, etc., but there's no reliable way to do this (AFAIK); the compiler may entirely eliminate or mangle certain things.

Essentially, for serialization, you will have to do the registration (semi-)manually. But you may be interested in a serialization library that will help out with the chores, such as Boost Serialization.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
1

Since there is no reflection in C++, I would suggest using an external script to scan your source code for all relevant classes (which is easy if you use empty dummy #defines to annotate them in the source code) and have it generate the registration code.

Alexander Gessler
  • 45,603
  • 7
  • 82
  • 122
  • 1
    This will work so long as you haven't got any class templates or other weird things... – Oliver Charlesworth Apr 26 '11 at 12:02
  • I would argue that even this will be relatively little work compared with manual registration - in a long term view :-). I've found using specialized scripts to extract some bits of information from source code and generate code out of it quite handy at several occasions .. but it surely depends on the case. – Alexander Gessler Apr 26 '11 at 12:05
1

I personally use the manual registration road. If you forget to register... then the test don't work anyway.

You just have to use a factory, and implement some tag dispatching. For example:

typedef void (*ActOnMessageType)(Message const&);

typedef std::map<std::string, ActOnMessageType> MessageDispatcherType;

static MessageDispatcherType& GetDispatcher() {
  static MessageDispatcherType D; return D;
}

static bool RegisterMessageHandler(std::string name, ActOnMessageType func) {
  return GetDispatcher().insert(std::make_pair(name, func)).second;
}

Then you just prepare your functions:

void ActOnFoo(Message const& m);
void ActOnBar(Message const& m);

And register them:

bool const gRegisteredFoo = RegisterMessageHandler("Foo", ActOnFoo);
bool const gRegisteredBar = RegsiterMessageHandler("Bar", ActOnBar);

Note: I effectively use a lazily initialized Singleton, in order to allow decoupling. That is the registration is done during the library load and thus each Register... call is placed in the file where the function is defined. The one difference with a global variable is that here the dispatching map is actually constant once the initialization ends.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • I already asked a question that involved [semi-auto types registration](http://stackoverflow.com/questions/5770872/how-to-tag-some-types-to-build-a-type-list-from-these-tagged-types-at-compile-tim). My TypeRegistry actually owns a map that binds a qualified name to a delegate able to create my concrete type. Do you think it's a non sense? Sorry for the crossreference. – mister why Apr 26 '11 at 13:23
  • @mister why: I tend to favor explicitness those days. Even this mechanism is not so explicit. I also tend to register pointer to functions rather than "types" or "exemplars". Your proposal makes sense, but not when it comes to decoupling, since it involves meta template programming. – Matthieu M. Apr 26 '11 at 14:26