2011-04-12 10 views
0

問題に少しぶつかり、最適なソリューションコンセプト/理論を探しています。モジュールとクラスの扱い(動的リンク)

私はオブジェクトを使用する必要があるシステムを持っています。システムが使用する各オブジェクトには既知のインタフェースがあり、抽象クラスとして実装されている可能性があります。インターフェイスはビルド時に認識され、変更されません。使用される正確な実装は異なりますし、事前にどのモジュールがそれを提供しているのか分かりません。唯一の保証は、彼らがインターフェースを提供することです。クラス名とモジュール(DLL)は、設定ファイルから取得するか、プログラムによって変更することができます。

は今、私は比較的単純なシステムを使用して、現時点で設定しているすべての、(ちょうど基本を表示するには、書き換えられた擬似コード)そうのようなものを設定している:

struct ClassID 
{ 
    Module * module; 
    int number; 
}; 

class Module 
{ 
    HMODULE module; 
    function<void * (int)> * createfunc; 

    static Module * Load(String filename); 

    IObject * CreateClass(int number) 
    { 
     return createfunc(number); 
    } 
}; 

class ModuleManager 
{ 
    bool LoadModule(String filename); 

    IObject * CreateClass(String classname) 
    { 
     ClassID class = AvailableClasses.find(classname); 
     return class.module->CreateObject(class.number); 
    } 

    vector<Module*> LoadedModules; 
    map<String, ClassID> AvailableClasses; 
}; 

モジュールは、いくつか持っていますそれらが提供するクラスの数およびそれらの名前/ IDを与えるためにエクスポートされた関数を呼び出す。すべてのクラスは、仮想デストラクタを持ち、ソースモジュールを格納し、クラスのID、それが実装するインタフェースなどを取得するいくつかのメソッドを持っています。IObjectから派生しています。

唯一の問題は、各モジュールを手動でどこかにロードする必要があることです(現時点では設定ファイルにリストされています)。私はこれを明示的に行うことを避けたいと思います(ModuleManagerの中で、その実装方法について本当に心配していません)。

モジュールの読み込みを処理せずに、オブジェクトを作成して(それがすべて設定されると)、魔法のように表示されます。

これは、COMが何らかの方法で行うことになっていると似ていると思います。私は簡単にCOMシステムを調べましたが、それは信じられないほどの余計なことです。私は自分のシステム内で知られているクラスだけが必要で、それが扱う他のすべての機能を必要とせず、どこかから来るインターフェースを実装するだけです。

私の他のアイデアは、レジストリを使用して、既知の/登録されたすべてのクラスとそのソースモジュールと番号を保持しているため、それらを検索するだけで、Manager::CreateClassが魔法のようにオブジェクトを見つけて作成するように見えます。これは実行可能な解決策のように思えますが、最適か、何かを再構築しているかどうかはわかりません。

だからこそ、私の質問は次のとおりです。これはどのように処理するのですか?既存の技術はありますか?それを自分で設定するにはどうすればいいですか?私が探していなければならないものはありますか?

答えて

1

COMはおそらくあなたが望むものです。非常に広いですが、すべての機能を使用する必要はありません。たとえば、参加者にGUIDの登録を要求する必要はなく、インターフェイスのインスタンスを作成する独自のメカニズムを定義できます。 COMインターフェイスを簡単に作成できるように、さまざまなテンプレートやその他のメカニズムが用意されています。さらに、標準であるため、要件を文書化するのは簡単です。

C++オブジェクトのインポート/エクスポートでは、すべての参加者が同じコンパイラを使用する必要があります。これまでに問題があると思われる場合は、COMを使用する必要があります。あなたがその制限を受け入れることを喜んでしているなら、あなたはあなたのままで続けることができます。

+0

コンパイラやランタイムを気にすることなく、C#モジュールの使用を許可するなど、COMが提供する機能のいくつかはかなりいいですが、COMでこの作業を行う方法についての情報はまだ見つかりません。私が新しいインターフェース/オブジェクトを作る際に見つけることができたのは、多くの定義済みの定型コードでした。見栄えの良いドキュメントに関する提案はありますか? – ssube

+0

私はCOMオブジェクトを作成するためのATLを見ていたと思います。私はDon Boxの本、Essential COMも読んでいます。実際には最初の2つの章だけが必要です。それは本当に恐ろしいことではありません! –

+0

この本には、どのように動作するかについての良い説明があります。また、MSDNドキュメントの中には、素敵なチュートリアル用のものがあります。これを試して、それがうまくいくかどうかを見に行く。提案していただきありがとうございます。 :) – ssube

1

これを行うための技術があるかどうかわかりません。

私はこれに非常に似たシステムで働いていたことを知っています。 XMLファイルを使用して、さまざまなモジュールが利用できるさまざまなクラスを記述しました。これと同等のModuleManagerは、提供されたクラス名とシステムの構成に基づいて、xmlファイルを解析して、実行時にユーザーのために何を作成するかを決定します。 (インタフェース 'I'を実装したオブジェクトを要求すると、システムの構成に応じてオブジェクトA、B、Cのいずれかが返されます)。

大きな問題は、非常に脆く、時にはデバッグ/理解が難しい。コードを読んでいるだけで、具体的なクラスがどのようにインスタンス化されているかを見ることは、ほとんど不可能でした。また、XMLを維持すると予想以上に多くのバグとオーバーヘッドが発生することもわかりました。

もし私がこれをやり直すのであれば、DLLのインターフェイスからクラスを公開するデザインパターンを維持しますが、クラスの中心的なレジストリを構築しようとはしません。 IObject。

代わりに、各モジュールが独自のファクトリ関数を公開してオブジェクトをインスタンス化するようにします。

+0

私の現在の設定では、各モジュールは3つの関数( 'int ClassCount()'、 'const char * ClassInfo(int)'と 'IObject * ClassCreate(int)')をエクスポートします。これは、あなたが記述したXML定義を避ける簡単な方法を提供し、組み込みのファクトリを提供します。 'IObject'ベースは、すべてのオブジェクトが、自分が何であるか、どこから来たのかを知っていることを保証します。 – ssube

+0

コード内に膨大な数のdynamic_cast文があるため、私たちのシステムで共通の基底クラスが嫌いでした。私の例では、すべてのオブジェクトをIObject *として返し、正しいインタフェースにキャストしました。ファクトリ関数は、たとえ複数の関数が必要な場合でも、意味のあるインタフェースを返すことを好みます。つまり、オブジェクトがどこから来たのかを知る必要がある場合、共通の基底クラスを使用することはできません。 – Nathanael

+1

ええ、私はあなたが何を意味し、どのようにそれはいくつかの利点を持つことができるかを参照してください。どのようなオブジェクトが(名前で)全体的に利用可能であったかをどのように扱っていましたか? – ssube

関連する問題