REALbasicでクラス名(String)からそのクラスのインスタンスを作る方法

REALbasicでは通常、インスタンスの作成には「New クラス名」という記述方法をする以外の方法はありません。

  Dim D as Dictuinary = New Dictionary

この時の「Dictionary」はあくまでコンパイル時に解釈されるので、実行時に変更する事はできないのだけど・・・


これがもし、

  Dim D as Dictuinary = Create("Dictionary")

みたいにできたら楽しいと思うの。


で、やってみた。

説明ややこしいのでソース全部のせます。

ポイントは、Introspectionを使ってClassInfo.Lookupメソッド(リファレンス未記載)を呼んで、文字列から該当クラスのTypeInfoを取得するところ。

未記載のクラス・メソッドを利用しているので一切公式の保証はありませんが、一応2008r5と2010r5で動作するらしいことを確認しました。
(本当に大丈夫なのかはわかりません。。)

function NewObject(ClassName as String,Params() as Variant) as Object

  '// Create a new instanse by ClassName string
  '// 2011 yuki@nekobooks.com
  '//
  '// ex: Dim o as Object = NewObject("Dictionary")
  
  
  'search 'Lookup' method
  If mLookup = Nil Then 'mLookup is Modul's property to chche ,and is null at first.
    'get an object of ClassInfo 
    'this ClassInfo object is used for calling 'Lookup' method
    Dim T as Introspection.TypeInfo = Introspection.GetType(Introspection.GetType(app)) 
    Dim Ms() as Introspection.MethodInfo = T.GetMethods
    
    'search 'Lookup' method 
    For each M as Introspection.MethodInfo In Ms
      Dim Ps() as Introspection.ParameterInfo = M.GetParameters()
      If M.Name = "Lookup" and UBound(Ps) = 0 Then
        If Ps(0).ParameterType.FullName = "String" Then
          mLookup = M 'cache Lookup method
          Exit
        End If
      End If
    Next
  End If
  
  If mLookup = Nil Then
    Return Nil 'fail to find Lookup method
  End If
  
  'Lookup target ClassInfo
  Dim LookupParam(0) as Variant
  LookupParam(0) = ClassName
  Dim TargetClassInfo as Introspection.TypeInfo = Introspection.TypeInfo(mLookup.Invoke(Nil,LookupParam))
  If TargetClassInfo = Nil Then
    Return Nil 'Class NOT Found
  End If
  
  'get constructors
  Dim CnstrI() as Introspection.ConstructorInfo = TargetClassInfo.GetConstructors()
  
  'Try each constructor
  Dim V as Variant
  For each C as Introspection.ConstructorInfo in CnstrI
    Try
      V = C.Invoke(Params) 'raise an exception if param count or type is missmatched. then try next
      Exit
    Catch TEx as TypeMismatchException
    End Try
  Next
  
  Return V.ObjectValue

End Function


面白いけど、どう使おう。。