Reflectionを利用して 動的にDLLファイルのクラスを扱う - C#

Reflectionを利用して 動的にDLLファイルのクラスを扱うコードを紹介します。

概要

動的に呼び出したメソッドからの戻り値がクラスの場合には、そのクラスを呼び出し側から扱う必要があります(メンバのアクセスやメソッドの呼び出しなど)。今回はリフレクションを用いてクラスを動的に扱う例を紹介します。
C#4.0のdynamic型を用いて同様の処理を実現する方法はこちらの記事を参照してください。

プログラム例

コード

FormMain.cs (呼び出し側)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;

namespace DynamicLoad
{
  public partial class FormMain : Form
  {
    public FormMain()
    {
      InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    //クラスタイプの参照ができる場合
    private void button5_Click(object sender, EventArgs e)
    {
      Assembly asm = Assembly.LoadFrom("SimpleLib.dll");
      Module mod = asm.GetModule("SimpleLib.dll");
      System.Type type = mod.GetType("SimpleLib.CalcClass");
      if (type != null) {
        Object obj = Activator.CreateInstance(type);

        MethodInfo addMethod = type.GetMethod("GetInfo");
        object ret = addMethod.Invoke(obj,null);

        SimpleLib.NameAndValue xnav = (SimpleLib.NameAndValue)ret;

        textBox1.Text = Convert.ToString(xnav.name);
        textBox2.Text = Convert.ToString(xnav.value);
      }
    }

    //クラスタイプの参照ができない場合
    private void button6_Click(object sender, EventArgs e)
    {
      Assembly asm = Assembly.LoadFrom("SimpleLib.dll");
      Module mod = asm.GetModule("SimpleLib.dll");
      System.Type type = mod.GetType("SimpleLib.CalcClass");
      if (type != null) {
        Object obj = Activator.CreateInstance(type);

        MethodInfo addMethod = type.GetMethod("GetInfo");
        object ret = addMethod.Invoke(obj,null);
        Type rett = ret.GetType();
        FieldInfo finame = rett.GetField("name");
        FieldInfo fivalue = rett.GetField("value");
      
        textBox1.Text = Convert.ToString(finame.GetValue(ret));
        textBox2.Text = Convert.ToString(fivalue.GetValue(ret));
      }
    }
  }
}
CalcClass.cs (ライブラリ側)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SimpleLib
{
  public class NameAndValue
  {
    public string name;
    public string value;
  }

  public class CalcClass
  {
    public int Add(int a, int b)
    {
      return a + b;
    }

    public NameAndValue GetInfo()
    {
      NameAndValue nav = new NameAndValue();
      nav.name = "SimpleLib";
      nav.value = "CalcClass";

      return nav;
    }

  }
}

解説

今回は呼び出し側からライブラリ側クラスCalcClassのGetInfo()メソッドを呼び出します。GetInfo()メソッドは戻り値がNameAndValueのクラスになっています。

クラスタイプの参照ができる場合

アセンブリを読み込み、モジュールと呼び出しクラスのタイプを取得します。
 Assembly asm = Assembly.LoadFrom("SimpleLib.dll");
 Module mod = asm.GetModule("SimpleLib.dll");
 System.Type type = mod.GetType("SimpleLib.CalcClass");

ライブラリクラスのインスタンスを作成します。
 Object obj = Activator.CreateInstance(type);

ライブラリクラスのメソッドを呼び出します。
 MethodInfo addMethod = type.GetMethod("GetInfo");
 object ret = addMethod.Invoke(obj,null);

戻り値のobject型をクラスにキャストします。
 SimpleLib.NameAndValue xnav = (SimpleLib.NameAndValue)ret;

フィールドの内容にアクセスし表示します。=
 textBox1.Text = Convert.ToString(xnav.name);
 textBox2.Text = Convert.ToString(xnav.value);

クラスタイプの参照ができない場合

アセンブリを読み込み、モジュールと呼び出しクラスのタイプを取得します。
 Assembly asm = Assembly.LoadFrom("SimpleLib.dll");
 Module mod = asm.GetModule("SimpleLib.dll");
 System.Type type = mod.GetType("SimpleLib.CalcClass");

ライブラリクラスのインスタンスを作成します。
 Object obj = Activator.CreateInstance(type);

ライブラリクラスのメソッドを呼び出します。
 MethodInfo addMethod = type.GetMethod("GetInfo");
 object ret = addMethod.Invoke(obj,null);

戻り値のObject型からGetType()メソッドを用いTypeクラスを取得します。取得したTypeクラスのGetFieldメソッドを呼び出し、フィールド情報(FieldInfoクラス)を取得します。
 Type rett = ret.GetType();
 FieldInfo finame = rett.GetField("name");
 FieldInfo fivalue = rett.GetField("value");

FieldInfoクラスのGetValue()メソッドを用い、フィールドの内容にアクセスし表示します。
 textBox1.Text = Convert.ToString(finame.GetValue(ret));
 textBox2.Text = Convert.ToString(fivalue.GetValue(ret));

著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2010-07-01
iPentec all rights reserverd.