プロが教えるわが家の防犯対策術!

VB.netで、
動的な型変換を行いたいと思っています。

イメージ的には、
CType(hogehoge,String)やCType(hogehoge,Integer)
CType(hogehoge,MyClassHogehoge)
ではなく、
CType(hogehoge,"String"),CType(hogehoge,"Integer")
CType(hogehoge,"MyClassHogehoge")
というように、

その場の変数で決まる型変換です。

Dim a as MyClassA
Dim b as Object
とあって
CType(b,a)というような変換をしたいのです。

(が、CTypeやDirectCastの第二引数は、
 定義された型名しか受け付け無いようです。)

-----

実際には、

mytype.InvokeMember("変数名", BindingFlags.SetProperty Or BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Instance, Nothing, "インスタンス", New [Object]() {"設定値"})

という処理をやる上で、

"設定値"が文字列(String)である場合、
"変数名"で、動的にアサインされた変数の型(たとえばMyClass)に型変換しないと、
値が設定できないためです。
(CType("設定値","インスタンス"."変数名")というようなこと必要となってくるはずです、、、)

-----

上記手順が、可能なのかどうか、
まったくのナンセンスなのかどうかも
わかっていないので、
一言でもいただけるとたすかります。。。
どうぞよろしくおねがいいたします。

A 回答 (5件)

思いっきりヘルプを引用


http://www.microsoft.com/japan/msdn/library/defa …

で、第二引数[typename]の解説で
>Dim ステートメントの As 句で有効な任意の式
とあります。
だから、コンパイル時に確定される型しかできません。

CTypeだけのピックアップされた質問なので、なぜ型を動的にしなければならないのかがわかりませんが、、、

どうしてもそうしなければいけないのであれば、それを解消する別手段を考えた方が、スムーズに行くと思いますよ。

この回答への補足

回答ありがとうございます。

> CTypeだけのピックアップ
CTypeにこだわっているわけではなく、
動的に型を変換したい、という意味で
「比ゆ的」にCTypeを説明につかわせてもらいました。
(わかりにくくて、すみません)

型を動的に変換したい理由は、
質問文中の
> mytype.InvokeMember("変数名", ~
のところで、"変数名"の型にそろえるように、毎回
> New [Object]() {"設定値"})
の型を変換しないと、例外がThrowされてしまうので、

「型を動的に変換したい」
と思っています。。。

補足日時:2005/08/19 12:25
    • good
    • 0

New [Object]() {"設定値"})


で落ちているのですよね・・・

受けのクラスが、どのようになっているのかがわからないので、
>型を変換しないと、例外がThrowされてしまうので、
と言われてもどうしようもないのですが。。。

全てのパターンを網羅するような、様々の型の受けることができるクラスを用意することにより対応した方がいいのでは?

たとえば
http://dobon.net/vb/dotnet/programing/typeinvoke …
でクラスの中に「StaticMethod」が二つありますよね?
引数が2個/3個のInteger型
となっていますが、同引数で文字型やらいりいろな型のパターンを切っておけば、その都度適した型のメソッドが実行されます。

動的な型変換ではなく、動的な関数を実行する方向では、代用できませんか?
    • good
    • 0

接続詞を間違ったために、私の発言したい事とニュアンスが全く異なる文章となったので、訂正いたします。



最後の一文
× 動的な型変換ではなく、動的な関数を実行する方向では、代用できませんか?
○ 動的な型変換ではなく、動的に関数を実行する方向では、代用できませんか?
    • good
    • 0
この回答へのお礼

何度も回答ありがとうございます。

Invokeのように、有用な機能があったので、
型の変換も、きっときれいにできるはずだ、と
思ってしまっていました。

複数の引数の型を用意する、よりもっと
どんくさいかもしれませんが、

Select文で型名ごとに分岐して
その都度Ctypeする方法で代用しようかと思います。
型の種類が(自前のクラスも含め)
膨大なので、躊躇していました。。。


考えあぐねていたところに、多くの示唆をいただきました。ありがとうございました。

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

(一応、やりたかったことのソースを添付します。
 最初に書くべきでした、、、すいません、、、)

Public Class MyClassA
Private _A As Integer
Private _B As Double
Private _C As Decimal
Private _D As String
Private _E As Object
Public Sub A(ByVal Value As Integer)
_A = Value
End Sub
Public Sub B(ByVal Value As Double)
_B = Value
End Sub
Public Sub C(ByVal Value As Decimal)
_C = Value
End Sub
Public Sub D(ByVal Value As String)
_D = Value
End Sub
Public Sub E(ByVal Value As Object)
_E = Value
End Sub
End Class

Public Class Sample
Sub init(ByVal pStr1 As String, ByVal pStr2 As String)
Dim ma As MyClassA = New MyClassA
Dim t As Type
t = ma.GetType
'↓OK ma.A(1)と同等
t.InvokeMember("A", BindingFlags.InvokeMethod, Nothing, ma, New [Object]() {1})

'↓NG
t.InvokeMember(pStr1, BindingFlags.InvokeMethod, Nothing, ma, New [Object]() {pStr2})
End Sub

<TestAttribute()> _
Sub main()
'/--- 呼び出しは、文字列型1と文字列型2の組み合わせ。(外部から、テキストで与えられる)
init("A", "1")
init("B", "1.5")
init("C", "1.15")
init("D", "aaa")
init("E", "bbb")
End Sub
End Class

お礼日時:2005/08/19 16:20

関数[init]の第二引数[pStr2]がStringなので、それようの受けを作る必要があります。



Stringでの受けができる状態にしておかないと、クラスに用意したメソッドが見つからなくて落ちます。
ただしObject型は、受けが発生してから領域を確保する変数なので、それは考慮する必要はありません。

以下のようにしたら可能かと思います。

Public Class MyClassA
  Private _A As Integer
  Private _B As Double
  Private _C As Decimal
  Private _D As String
  Private _E As Object

  Public Sub A(ByVal Value As Integer)
    _A = Value
  End Sub
  Public Sub B(ByVal Value As Double)
    _B = Value
  End Sub
  Public Sub C(ByVal Value As Decimal)
    _C = Value
  End Sub
  Public Sub D(ByVal Value As String)
    _D = Value
  End Sub
  Public Sub E(ByVal Value As Object)
    _E = Value
  End Sub

  Public Sub A(ByVal Value As String)
    Call A(CInt(Value))
  End Sub
  Public Sub B(ByVal Value As String)
    Call B(CDbl(Value))
  End Sub
  Public Sub C(ByVal Value As String)
    Call C(CDec(Value))
  End Sub
End Class
    • good
    • 0
この回答へのお礼

なるほど!
ありがとうございます。
参考になります。

お礼日時:2005/08/19 18:44

> Select文で型名ごとに分岐して


> その都度Ctypeする方法で代用しようかと思います。

> '/--- 呼び出しは、文字列型1と文字列型2の組み合わせ。(外部から、テキストで与えられる)
> init("A", "1")

init内で文字列"1"をint型の1に変換するのですよね。
キャスト(Ctype)では出来ないはずですが...

http://www.atmarkit.co.jp/fdotnet/dotnettips/001 …

> 型の種類が(自前のクラスも含め)

文字列を自前クラスへの型変換なんてできるのでしょうか?

# XMLシリアライス/デシリアライズならありえますが

この回答への補足

CTypeで無理なものは、
ソースをごりごり書くつもりでした。

>文字列を自前クラスへの型変換なんてできるのでしょうか?

も、単純にキャストが不可能なものは、
自前クラスをコンストラクトする、ことを考えてました。

舌足らずですみませんでした。

補足日時:2005/08/19 18:44
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!