文字列で指定したクラスのインスタンスを作成するには?.NET TIPS

» 2005年12月09日 05時00分 公開
[遠藤孝信デジタルアドバンテージ]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「.NET TIPS」のインデックス

連載目次

 通常、クラスのインスタンスはnewキーワード(VB.NETの場合はNewキーワード)により作成するが、リフレクションの機能により、文字列で指定されたクラス名からインスタンスを作成することもできる。

 本稿では、インスタンス化したいクラスを含んだアセンブリがすでにロードされている場合と、そのアセンブリがまだロードされていない場合の2つのケースについて、クラス名からインスタンスを作成する方法について解説する。

すでにアセンブリがロードされている場合

 インスタンス化したいクラスを含んだアセンブリがすでにディスクからロードされている場合には、まずTypeクラス(System名前空間)のGetTypeメソッドにより、そのクラスのTypeオブジェクトを得る。GetTypeメソッドでは、パラメータとしてクラス名を文字列で指定できる。

Type t = Type.GetType("インスタンス化したいクラス名");

 Typeオブジェクトは、特定のクラス(型)に関する情報を含んだオブジェクトである。Typeオブジェクトが得られれば、Activatorクラス(System名前空間)のCreateInstanceメソッドにより、そのTypeオブジェクトが示すクラスのインスタンスを作成できる。

object o = Activator.CreateInstance(t);

 このCreateInstanceメソッドは作成したインスタンスをobject型として返すため、そのインスタンスのメンバにアクセスするには何らかのキャストが必要となる。

 以下にこれら2つのメソッドを利用した例を示す。

// createinstance.cs

using System;

public class MasterClass {
  public virtual void Say() {
    Console.WriteLine("Use the Force");
  }
}

public class PadawanClass : MasterClass {
  public override void Say() {
    Console.WriteLine("Yes, Master");
  }
}

public class JediMaster {
  static void Main() {
    Type masterType = Type.GetType("MasterClass");
    MasterClass obiwan
      = (MasterClass)Activator.CreateInstance(masterType);
    obiwan.Say(); // 出力:Use the Force

    Type padawanType = Type.GetType("PadawanClass");
    MasterClass anakin
      = (MasterClass)Activator.CreateInstance(padawanType);
    anakin.Say(); // 出力:Yes, Master
  }
}

// コンパイル方法:csc createinstance.cs

クラス名からインスタンスを作成するC#のサンプル・プログラム(createinstance.cs)
createinstance.csのダウンロード

' createinstance.vb

Imports System

Public Class MasterClass
  Public Overridable Sub Say()
    Console.WriteLine("Use the Force")
  End Sub
End Class

Public Class PadawanClass
        Inherits MasterClass
  Public Overrides Sub Say()
    Console.WriteLine("Yes, Master")
  End Sub
End Class

Public Class JediMaster
  Shared Sub Main()
    Dim masterType As Type = Type.GetType("MasterClass")
    Dim obiwan As MasterClass = _
      CType(Activator.CreateInstance(masterType), MasterClass)
    obiwan.Say() ' 出力:Use the Force

    Dim padawanType As Type = Type.GetType("PadawanClass")
    Dim anakin As MasterClass = _
      CType(Activator.CreateInstance(padawanType), MasterClass)
    anakin.Say() ' 出力:Yes, Master
  End Sub
End Class

' コンパイル方法:vbc createinstance.vb

クラス名からインスタンスを作成するVB.NETのサンプル・プログラム(createinstance.vb)
createinstance.vbのダウンロード

 このサンプル・プログラムには、インスタンス化したいクラス(MasterClassクラスやPadawanClassクラス)とインスタンス化のためのコードの両方が含まれているため、GetTypeメソッドをいきなり呼び出して、それらのクラスのTypeオブジェクトが取得可能である。

まだアセンブリがロードされていない場合

 アセンブリがまだロードされていない場合には、まずそのアセンブリを明示的にロードしてやる必要がある。これにはAssemblyクラス(System.Reflection名前空間)のLoadFromメソッドが使える。パラメータには、ロードしたいアセンブリを含むファイル(通常はDLLファイル)のパス名を指定する。

Assembly asm = Assembly.LoadFrom("アセンブリのファイル名");

 Assemblyオブジェクトは、特定のアセンブリに関する情報を含んだオブジェクトである。このAssemblyクラスにも、Typeクラスと同様にGetTypeメソッドが用意されており、クラス名により、そのアセンブリに含まれるクラスのTypeオブジェクトを作成できる。

Type t = asm.GetType("インスタンス化したいクラス名");

 Typeオブジェクトを取得できれば、あとは先ほどと同様にActivator.CreateInstanceメソッドによりインスタンス化が可能だ。以下にその例を示す。

 なお以下のプログラムでは、MasterClassクラスとPadawanClassクラスが「jedi.dll」というDLLファイル(後掲)に含まれているものとする。コンパイル時にはjedi.dllを参照する必要がある。

// main.cs

using System;
using System.Reflection;

public class JediMaster {
  static void Main() {
    Assembly asm = Assembly.LoadFrom("jedi.dll");

    Type masterType = asm.GetType("MasterClass");
    MasterClass obiwan
      = (MasterClass)Activator.CreateInstance(masterType);

    // 上の3行は次のようにも記述可能

    // MasterClass obiwan
    //  = (MasterClass)asm.CreateInstance("MasterClass");

    obiwan.Say(); // 出力:Use the Force

    Type padawanType = asm.GetType("PadawanClass");
    MasterClass anakin
      = (MasterClass)Activator.CreateInstance(padawanType);

    // 上の3行は次のようにも記述可能
    // MasterClass anakin
    //   = (MasterClass)asm.CreateInstance("PadawanClass");

    anakin.Say(); // 出力:Yes, Master
  }
}

// コンパイル方法:csc /r:jedi.dll main.cs

アセンブリをロードしてクラス名からインスタンスを作成するC#のサンプル・プログラム(main.cs)
main.csのダウンロード

' main.cs

Imports System
Imports System.Reflection

Public Class JediMaster
  Shared Sub Main()
    Dim asm As [Assembly] = [Assembly].LoadFrom("jedi.dll")

    Dim masterType As Type = asm.GetType("MasterClass")
    Dim obiwan As MasterClass = _
      CType(Activator.CreateInstance(masterType), MasterClass)

    ' 上の3行は次のようにも記述可能
    ' Dim obiwan As MasterClass = _
    '  CType(asm.CreateInstance("MasterClass"), MasterClass)

    obiwan.Say() ' 出力:Use the Force

    Dim padawanType As Type = asm.GetType("PadawanClass")
    Dim anakin As MasterClass = _
      CType(Activator.CreateInstance(padawanType), MasterClass)

    ' 上の3行は次のようにも記述可能
    ' Dim anakin As MasterClass = _
    '  CType(asm.CreateInstance("PadawanClass"), MasterClass)

    anakin.Say() ' 出力:Yes, Master
  End Sub
End Class

' コンパイル方法:vbc /r:jedi.dll main.vb

アセンブリをロードしてクラス名からインスタンスを作成するVB.NETのサンプル・プログラム(main.vb)
main.vbのダウンロード

 続いてjedi.dllのソース・コードを示す。

// jedi.cs

using System;

public class MasterClass {
  public virtual void Say() {
    Console.WriteLine("Use the Force");
  }
}

public class PadawanClass : MasterClass {
  public override void Say() {
    Console.WriteLine("Yes, Master");
  }
}

// コンパイル方法:csc /t:libarary jedi.cs

C#によるjedi.dllのソース・コード(jedi.cs)
jedi.csのダウンロード

' jedi.vb

Imports System

Public Class MasterClass
  Public Overridable Sub Say()
    Console.WriteLine("Use the Force")
  End Sub
End Class

Public Class PadawanClass
        Inherits MasterClass
  Public Overrides Sub Say()
    Console.WriteLine("Yes, Master")
  End Sub
End Class

' コンパイル方法:vbc /t:library jedi.vb

VB.NETによるjedi.dllのソース・コード(jedi.vb)
jedi.vbのダウンロード

 上記のmain.cs(main.vb)中にコメントで示したように、AssemblyクラスにもCreateInstanceメソッドが用意されており、このメソッドを利用すればTypeオブジェクトの作成部分をショートカットできる。

カテゴリ:クラス・ライブラリ 処理対象:リフレクション
使用ライブラリ:Typeクラス(System名前空間)
使用ライブラリ:Activatorクラス(System名前空間)
使用ライブラリ:Assemblyクラス(System.Reflection名前空間)

「.NET TIPS」のインデックス

.NET TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。