C# の属性、リフレクション

  • 属性とは、以下のように、メタデータを追加する仕組みのことです。
[assembly: AssemblyTitle("")] // AssemblyInfo.cs 内
 
[Serializable]
Class MySerializableClass
{
}

以下のように独自の属性を作ることもできます。

public class BugFixAttribute : System.Attribute
{
  int BugID;
  String Comment, Date, Programmer;
  public BugFixAttribute( int bugID, String programmer, String date )
  {
    this.BugID = bugID; this.Programmer = programmer; this.Date = date;
  }
}

[BugFixAttribute( 121, "Jack", "2008/11/24", Comment = "Hello World" )] //!<属性の付加
public class MyTest
{
// ... 何かコード
}
  • リフレクションとは、プログラムが自身のメタデータを読み取る、あるいは他のプログラムのメタデータを読み取る際の処理のことをいいます。
public static void Main()
{
  MyTest t = new MyTest();
  System.Reflection.MemberInfo inf = typeof(MyMath);
  Object[] attributes = inf.GetCustomAttributes(typeof(BugFixAttribute), false);

  foreach(Object attribute in attributes) //!<属性を調べてプロパティを表示
  {
    BugFixAttribute a = (BugFixAttribute)attribute;
    Console.WriteLine("BugID={0}, Programmer={1}, Date={2}, Comment={3}", a.BugID, a.Programmer, a.Date, a.Comment);
  }
}
  • リフレクションを使うことで、以下のようにアセンブリ内の、メソッドやプロパティなどの情報を探索することができます。
public class MyTest
{
  public static void Main()
  {
    Assembly a = Assembly.Load("Mscorlib"); //!< アセンブリの動的な読み込み
    Type[] types = a.GetTypes();
    foreach (Type t in types)
    {
      Console.WriteLine("Type={0}", t);
      foreach (MemberInfo i in t.GetMembers()) Console.WriteLine("{0}={1}", i, i.MemberType);
    }
  }
}
  • 実行時での、動的なメソッドの呼び出し (実行時バインディング)は以下のように行います。
public class MyTest
{
  public static void Main()
  {
    Type typeMath = Type.Get("Sysmte.Math");
    // Math は static クラスなのでインスタンスは不必要
    // Object obj = Activator.CreateInstance(typeMath);

    // 引数の型の指定
    Type[] typeParams = new Type[1];
    typeParams[0] = Type.GetType("Sysmte.Double");

    // 関数の探索
    MethodInfo infoCos = typeMath.GetMethod("Cos", typeParams);

    // 引数のインスタンスの作成
    Object[] parameters = new Object[1];
    parameters[0] = 45.0 * 3.14 / 180;
    
    // 関数の呼び出し
    Object val = infoCos.Invoke(typeMath, parameters);
    Console.WriteLine("コサイン45度は {0}", val);
  }
}