- PR -

VBにおいて動的にクラスを設定する方法

投稿者投稿内容
さとる
会議室デビュー日: 2007/05/09
投稿数: 2
投稿日時: 2007-05-09 11:50
はじめまして。初めて書き込みさせていただきます。
皆様に質問があります。

VBにおいて、動的にクラス名を設定し取り扱う方法はございますでしょうか?


要するに、今
スーパークラス:clsSuperClass
クラスA:clsSubClassA Inherits clsSuperClass
クラスB:clsSubClassB Inherits clsSuperClass
クラスC:clsSubClassC Inherits clsSuperClass

があった場合。

Dim strClassName As String = "clsSubClassA"

このstrClassNameの変数を使用して、strClassNameに設定されているクラスを呼び出したいのです。
strClassNameには、"clsSubClassB"、"clsSubClassC"も入り得ります。


ちなみに、こういう感じのコードを組もうとしています。
-------------------------------------------------------------------------
それぞれ計算ロジックを持っているclsSubClassA,clsSubClassB,clsSubClassCに、
計算数値元および計算結果領域を格納しているclsCalcResultClassを与えて、
clsSubClassA,clsSubClassB,clsSubClassCの計算の合算値をclsCalcResultClassに格納しようとしている。
計算クラスのcalc関数の引数・返り値の仕様は同一である。
-------------------------------------------------------------------------

Dim calcResult As New clsCalcResultClass

Dim lstClass As New ArrayList
lstClass.Add("clsSubClassA")
lstClass.Add("clsSubClassB")
lstClass.Add("clsSubClassC")

For intIndex = 0 To lstClass.Length - 1
Dim objCalcClass As New (*lstClass(intIndex)) ←ここの箇所の書き方がわからない
objCalcClass.calc(calcResult)
Next intIndex

return calcResult

-------------------------------------------------------------------------

VBでは、eval関数が使えないらしいので、どう組めばいいのか悩んでいます。
皆様、どうぞよろしく知恵をお貸しください。

以上。よろしくお願いします。
_________________
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2007-05-09 12:12
どうもクラスとインスタンスがごっちゃになっている感じがします。

コード:

Dim calcs As New ArrayList
calcs.Add(New clsSubClassA())
calcs.Add(New clsSubClassB())
calcs.Add(New clsSubClassC())

For Each calculator As clsSuperClass In calcs
    calculator.calc(calcResult)
Next


で十分ではないですか?
何故、文字列の介入が必要なのでしょうか。
ぶさいくろう
ぬし
会議室デビュー日: 2005/11/22
投稿数: 1232
お住まい・勤務地: 川崎市(は俺も含めてロクな人間が住んでないよw)
投稿日時: 2007-05-09 12:12
リフレクションを使えばいいところだけど設計がおかしいからみなおした方がいいよ。
戻り値とかすべてひっくるめて見直した方がいい。

>計算クラスのcalc関数の引数・返り値の仕様は同一である。
だったら、

>クラスA:clsSubClassA Inherits clsSuperClass
>クラスB:clsSubClassB Inherits clsSuperClass
>クラスC:clsSubClassC Inherits clsSuperClass
なんで3つあるのかよくわかんない。
何のためのクラスなんだろう。データを保持してなさげなのに。

>計算数値元および計算結果領域を格納しているclsCalcResultClassを与えて、
これだけは絶対におかしい。結果の箱を与えるな。結果だけ勝手にもらいなさい。
SourceとDestinationをいっしょくたにするのもおかしい。

>VBでは、eval関数が使えないらしいので、どう組めばいいのか悩んでいます。
なんでいきなり関係のない話題が出てくるの?理解できない。
masa
大ベテラン
会議室デビュー日: 2004/10/28
投稿数: 161
投稿日時: 2007-05-09 12:59
デザインパターンでいう「Command」のサンプルに出てきそうな処理ですね。

引数の数が多いとか、前処理の結果を引き継いで次の処理を行うような場合には
ひとまとめにして処理クラスに渡すという設計もありだとは思います。
ただ、処理クラスによって何が書き換えられるかとかが不明瞭であったり、
書き換えられる順番に依存性が出たりすると設計が破綻するかもしれません。

このページなんかはどうでしょう。
http://hccweb1.bai.ne.jp/tsune-1/VisualBasic/command.html


「動的に呼び出す」ことについては、
わざわざ文字列表現を経由する必要はないように思えますが、
設定ファイルから読み込んだりすることを考えているのでしょうか?


かるあ
ぬし
会議室デビュー日: 2003/11/16
投稿数: 1190
お住まい・勤務地: センガワ→ムサシノ
投稿日時: 2007-05-09 13:04
設定ファイルなどに書かれたクラスのインスタンスでも作成するんでしょうか。

ぶさいくろうさん のおっしゃっているようにリフレクションを使えばできますが、
本当にその機能が必要なのかをもう少し考えたほうがいい。
リフレクションはだいたい保守が大変になるしね。

プラグインの勉強をすると理解しやすいですね。
_________________
かるあ のメモスニペット
かるあ
ぬし
会議室デビュー日: 2003/11/16
投稿数: 1190
お住まい・勤務地: センガワ→ムサシノ
投稿日時: 2007-05-09 13:04
設定ファイルなどに書かれたクラスのインスタンスでも作成するんでしょうか。

ぶさいくろうさん のおっしゃっているようにリフレクションを使えばできますが、
本当にその機能が必要なのかをもう少し考えたほうがいい。
リフレクションはだいたい保守が大変になるしね。

プラグインの勉強をすると理解しやすいですね。
_________________
かるあ のメモスニペット
kanai
ベテラン
会議室デビュー日: 2004/09/13
投稿数: 98
投稿日時: 2007-05-09 13:22
kanaiです。

リフレクションを使うとこんな感じでしょうか。

コード:

Dim objCalcClass As clsSuperClass = CType(Activator.CreateInstance(Type.GetType(CStr(lstClass(intindex)))), clsSuperClass)



lstClass(intindex)にはクラス名だけでなく、名前空間まで含めて指定する必要があったと記憶しています。

[追記]
単にActivator.CreateInstanceを使っているだけなので、これは「リフレクション」とは言わないのかもしれません。


[ メッセージ編集済み 編集者: kanai 編集日時 2007-05-09 13:28 ]
さとる
会議室デビュー日: 2007/05/09
投稿数: 2
投稿日時: 2007-05-09 16:38
 皆様、お忙しい中ありがとうございました。


 文字列介入の必要は、DBから動的に使用するクラスを引き出す仕組みだからです。
 クラスが持つ計算式はそれぞれが複雑で独立している上、今後とも追加していく可能性が濃厚である、さらに計算式を利用する人がユーザごとに違う状況であるため、今回のような仕様になったということです。

 DBで使用するクラス名を設定したほうがいいかな、と。

 当初、eval関数を使用して動的にコードを作成することで対応しようと考えていたのですが、それが使えないことが午前中に発覚したため、大慌てでこちらに書き込みさせていただいた次第です。最初の書き込みで意味不明な箇所があったことをお詫びいたします。
 また、結果の箱を与えるのはmasa様のおっしゃるとおり、引数の数がえらい多い処理になりますので、結果の箱を先に与えるやり方にしました。最後に結果の箱を取得するやり方にしようかどうしようか、今現在悩んでいるところです。@現在は処理成功時trueを返すやり方。

 しかし、デバックを考えると、確かに気が遠くなりそうですよね。。。
 もう少しメンテナンス周りで考えてみる必要があるかも知れません。
 そもそも内部で再帰ロジックを考えているので、テストやメンテナンスのことを考えないと、危険なものになりかねないですので。
 もう少し頑張りますです。

 最後に、
>kanai様
 サンプルコードありがとうございました。
 参考にさせていただきます。




_________________

スキルアップ/キャリアアップ(JOB@IT)