none
デザイン時に、自身のプロジェクトのアセンブリをロードしたい RRS feed

  • 質問

  • 初めて質問させて頂きます。

    C#2005で作ってます。

    カスタムコンポーネントのプロパティにて、System.Windows.Formsを
    継承しているフォームのTypeを登録したいと思っています。
    編集中プロジェクト自身、編集中プロジェクト内で参照設定が行われている
    コンポーネント内の、全てのフォームのTypeを取得したいのです。

    同一ソリューション内でコンポーネントプロジェクトとテストプロジェクトを配置して
    テストプロジェクトをビルドした場合、ビルドしたからか、そこそこ望みどおりの動作
    をします。

    カスタムコンポーネントの該当部で行っているコードは以下の通りです。

    List<KeyValuePair<string, Type>> list = new List<KeyValuePair<string, Type>>();
    Assembly[] asms = AppDomain.CurrentDomain.GetAssemblies();
    foreach (Assembly asm in asms)
    {
        Type[] types = asm.GetTypes();
        foreach (Type type in types)
        {
            Type compareType = null;
            compareType = typeof(Form);
            if (compareType.IsAssignableFrom(type))
            {
                list.Add(new KeyValuePair<string, Type>(type.FullName, type));
            }
        }
    }

    そこでコンポーネントプロジェクトをdll化し、別ソリューション・プロジェクトを
    作成して、そこでdllを参照設定に追加、カスタムコンポーネントの配置を
    行いました。

    しかし、現在編集を行っているプロジェクト内に存在するフォームのTypeが
    取得できません。
    試しに、編集中プロジェクト内に適当なコンポーネントを作成し、ツールボックスから
    そのコンポーネントをフォーム上に貼り付けると、アセンブリがロードされるのか、
    編集中プロジェクト内のフォームを取得することが出来ました。

    どうやら同様に、参照設定が行われているdllなども、何か1つでもコンポーネントが
    貼り付けられないとアセンブリがロードされていないようで、取得が行えませんでした。

    私がやろうとしていることは実現できないのでしょうか?

    2012年7月13日 3:18

回答

  • 本筋の話は申し訳ないですが、よい案が提示できません。
    拡張プロバイダも同じデザイナで配置しているオブジェクトが限界だと思われるので…。

    例えばなんですが、参照設定が行われている全てのアセンブリおよび、自身を
    強制的にアセンブリロードする方法などはありますでしょうか?
    自身などの編集中のものは、ビルドされている前提で構わないのですが。
    完璧である必要はありませんが、今以上には精度を上げたいと思っています。

    仮にそんなことができたとしてもやらない方がよいのではないかと思っています。
    相当にうまくやらないと、アセンブリがロードされたままになり、再ビルド時に上書きできなくなって、デザイナを開いた後にビルドし直す際に、Visual Studio を再起動しなければならないという、非常に不便な環境になりかねません。

    // Visual Studio 自身が開いたアセンブリはうまくアンロードさせているようなので、
    // 同じ AppDomain ならうまくいくかもしれませんが、リスクは大きいと思います。

    2012年7月14日 13:25
    モデレータ

すべての返信

  • このシナリオにおける CurrentDomain は Visual Studio のプロセス内のわけですから、必要なアセンブリしか読み込まれていません。この必要なアセンブリとは、デザイナで貼り付けられているユーザーコントロールを描画、プロパティの取得・設定、シリアライズに必要なアセンブリのことです。この必要性がないアセンブリが読み込ません。
    また、デザイナで編集している途上の場合、そのデザイン対象のクラスはビルドされていませんから、取得できません。

    このように、今のリフレクション方式では限界があります。(ビルドされているかつ読み込まれていることが前提となる)
    デザイナ向けのクラスも用意されていたとは思いますが、ビルドされていないプロジェクトの型まできちんと検索、フォローできない可能性があります。この場合、自分でコンパイル、解析するようなアドオン的な存在になってくるのではないでしょうか…。

    // もしかしたら楽になる方法があるかもしれません。
    // ただ、期待薄なので、できない or 難しいのではないかと思っています。

    2012年7月13日 14:47
    モデレータ
  • よく要件として挙がってくるものとして、ある画面Aより、特定コントロール配下で
    参照ボタンやファンクションキーを押した際にモーダルで画面Bが表示されるという
    ことがあると思います。
    その表示される画面Bを、プロパティで予め設定できればと思っていたんです。

    別な場面でクラスやコンポーネントが利用されていれば別ですが、そうでない場合に
    選べないというのは些か不便でして。
    参照設定されているんだから、デザイナ上で探査できてもいいんじゃないか、と。

    例えばなんですが、参照設定が行われている全てのアセンブリおよび、自身を
    強制的にアセンブリロードする方法などはありますでしょうか?
    自身などの編集中のものは、ビルドされている前提で構わないのですが。
    完璧である必要はありませんが、今以上には精度を上げたいと思っています。

    2012年7月14日 10:06
  • 本筋の話は申し訳ないですが、よい案が提示できません。
    拡張プロバイダも同じデザイナで配置しているオブジェクトが限界だと思われるので…。

    例えばなんですが、参照設定が行われている全てのアセンブリおよび、自身を
    強制的にアセンブリロードする方法などはありますでしょうか?
    自身などの編集中のものは、ビルドされている前提で構わないのですが。
    完璧である必要はありませんが、今以上には精度を上げたいと思っています。

    仮にそんなことができたとしてもやらない方がよいのではないかと思っています。
    相当にうまくやらないと、アセンブリがロードされたままになり、再ビルド時に上書きできなくなって、デザイナを開いた後にビルドし直す際に、Visual Studio を再起動しなければならないという、非常に不便な環境になりかねません。

    // Visual Studio 自身が開いたアセンブリはうまくアンロードさせているようなので、
    // 同じ AppDomain ならうまくいくかもしれませんが、リスクは大きいと思います。

    2012年7月14日 13:25
    モデレータ
  • ありがとうございます。
    一度でもアセンブリが読み込まれればいいようなので、ちょっと制限ありですが、そのまま行こうと思います。
    コード上でもフォローできることですし・・・。

    2012年7月16日 13:04