3

私はESBを持っています。シリアル化されたメッセージは、独自の完全修飾名 (つまり、名前空間 + クラス名) を転送します。実行する特定のロジックをカプセル化する各メッセージの具象型があります。
メッセージを受信するたびに、最初に逆シリアル化する必要があります。これにより、具体的な型に応じて、その操作をもう一度実行できます。

コンパイル時またはアプリケーションの初期化中にすべてのクラスを登録する方法が必要です。
.net では、リフレクションを使用してアセンブリをスキャンし、初期化中にメッセージの種類を検出しますが、C++ ではどのようにしますか?

4

3 に答える 3

3

C++ にはリフレクション機能がありません。オブジェクトファイルなどをスキャンしようとすることもできると思いますが、これを行う信頼できる方法はありません(AFAIK)。コンパイラは、特定のものを完全に削除または破壊する場合があります。

基本的に、シリアライゼーションでは、登録を (半) 手動で行う必要があります。しかし、 Boost Serializationなどの雑用に役立つシリアライゼーション ライブラリに興味があるかもしれません。

于 2011-04-26T11:55:24.983 に答える
1

個人的には手動登録道路を利用しています。登録を忘れた場合...テストはとにかく機能しません。

ファクトリを使用し、タグディスパッチを実装するだけです。例えば:

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;
}

次に、関数を準備します。

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

そしてそれらを登録します:

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

注:デカップリングを可能にするために、遅延初期化されたシングルトンを効果的に使用します。つまり、登録はライブラリのロード中に行われるため、各Register...呼び出しは関数が定義されているファイルに配置されます。グローバル変数との1つの違いは、初期化が終了すると、ディスパッチングマップが実際には一定であるということです。

于 2011-04-26T12:25:37.593 に答える
1

C++ にはリフレクションがないため、外部スクリプトを使用してソース コードをスキャンし、関連するすべてのクラスを見つけて (空のダミー #define を使用してソース コードに注釈を付ければ簡単です)、登録コードを生成することをお勧めします。 .

于 2011-04-26T12:02:02.033 に答える