NET対応言語

Introduction to C#
1
アジェンダ
•
•
•
•
•
•
•
•
•
.NET概説
基本要素
オブジェクト指向サポート
インターフェース
イベント/デリゲート
例外処理
GC
リフレクション
モジュール配布
2
.NET概説
3
.NET概説
•
•
•
•
•
•
.NETとは
.NETによって変わること
.NET Frameworkのメリット
.NET対応言語
C#とは
.NETの仕組み 実行手順
4
.NETとは
•
•
.NET
– 単に 「.NET」 と言うときは、 「.NET 戦略」 を指す。 すなわち、 Microsoft
の戦略を表す言葉で、 一言で表すと 「アプリケーションから Web サービ
スへ」 となる。
.NET Framework
– .NET 戦略にふさわしい、 次世代 OS を意味する。 最初は、 Windows
の上に .NET Framework という 「皮」 を被せて実現する。
5
.NETによって変わること
• x86からMSILへ
– x86CPU用のマシン語→ MSIL (CPUに依存しない中間言語)
• WindowsAPIからCLRへ
– 複雑になったWindowsAPI→新設計のCLR(実行環境)
• COMからBCLへ
– COM→CLR上に構築されたBCL(基本クラスライブラリ)
• 言語間の垣根が低くなる
– .NET対応言語は共通してCLS規格を満たしている
• レジストリから.cfgファイルへ
– レジストリ→cfgファイル(テキストファイル)
• アセンブリのバージョン管理
– 使用する共有アセンブリのバージョン指定が実行時に必須となり、dll
バージョン不一致が解消される。
6
.NET Frameworkのメリット
• プログラムの安全な実行
– プログラムの実行がCLRによって管理されることでGCやタイプ
セーフの恩恵を受ける。
• アプリケーションの容易な配布
– インストール時にレジストリ登録などが不要。
– バージョン管理機能を持っている。
• マルチ言語の開発環境
– C#やVB.NETなど複数のプログラミング言語を使ってひとつのも
のを作ることができる。
– 過去のソフトウェア資産を活用できる。
7
.NET対応言語
• .NET対応の言語はCLS規格にのっとっているた
め、出来ることは(だいたい)同じである。
• どの言語を使ってもコンパイルすればCLSにのっ
とったMSILになる。
8
C#とは
• シンプルかつ強力
–
ヘッダファイルとマクロ機能、多重継承の廃止
• バグの作りこみを防ぐ言語仕様
–
–
if(a=b)などはコンパイルエラーになる
ポインタを原則的に廃止
• 習得しやすい
–
–
ベースクラスライブラリはC#、VB.NET等で共通
C/C++の構文の多くを踏襲している
• プログラムの安全な実行
–
–
GCによるメモリリークの防止やタイプセーフなどがCLRによって実現されている
強力な構造化例外処理機構
• 相互運用性
–
–
COM+をフルサポート
Win32APIのようなネイティブコードを直接呼び出せる
9
.NETの仕組み 実行手順
.NET対応言語(C#など)
で書かれたソースコード
.NET対応コンパイラ
DLL or EXE のアセンブリ
(MSILとメタデータ)
.NET開発環境
・クラスローダ
・Just In Timeコンパイラ
プラットフォームに依存した命令
• どの言語を使っても
ソースコードをコンパ
イルすると中間言語
(MSIL)になる。
• 実行時はJITコンパイ
ラによってプラット
フォームに依存した
命令になる。
実行
.NET実行環境
10
基本要素
11
基本要素
•
•
•
•
•
•
値と参照
System.Object
“const”キーワード
アクセス修飾子
パラメータ修飾子
“namespace”
12
値と参照
• C#のデータタイプは「値型」か「参照型」のみ
• 値ベースのタイプ
– 値データタイプ(整数、浮動少数点、boolなど)
– 列挙型
– 構造体
• 参照ベースのタイプ
–
–
–
–
–
クラス
Object
String
配列
デリゲート
13
値タイプと参照タイプの違い
相違点
値
参照
アロケート場所
スタック
ヒープ
ベースタイプ
System.Value
他のベースタイ
プになれるか
不可
Sealedでない任
意のタイプ
可
パラメータで渡さ 値
れたときは
破棄のタイミング スコープを抜け
たとき
参照(変数のアド
レスが渡される)
GCが働くとき
14
System.Object
• C#のすべての型のベースクラス
• 以下のメンバを持つ
– Equals:参照を比較
– GetHashCode:インスタンスを識別する
– GetType:現在参照しているオブジェクトのType
を戻す
– ToString:<名前空間>.<クラス名>を返す
– Finalize:オブジェクト破棄前に呼ばれる
– MenberwiseClone:簡易コピーを作成する
15
Object型の提供メソッド
• オーバーライド可能
• 注意するメソッド
– GetType
• RTTIを行うために利用
– MemberwiseClone
• EqualsはFALSEを返す
• ReferenceEqualsはFALSEを返す
16
“const”キーワード
• “const”キーワードを利用して、定数データ
タイプを作成する
• 利用するシナリオ:
– クラス内定数
• 全インスタンスに定数を持たせることが可能
– 定数クラスを作成
• C# ではグローバル変数を定義できないので
• この場合、コンストラクタを“private”にしてインスタ
ンス生成を防ぐ
17
パラメータ修飾子
修飾子
説明
(なし)
値が変更されない入力パラメータ
out
呼び出されたメソッドで値が変更される
ref
呼び出し側、呼び出されたメソッド内で値
が更新される
複数パラメータを送る
params
18
注意:“out”と“ref”
• “out”と“ref”は呼び出し側でも記述する
– object.method(i, out j);
– object.method(i, ref j);
• “out”と“ref”の違い
– out:呼び出し側で初期化する必要なし
– ref:呼び出し側で初期化する必要あり
• “ref”初期設定の理由
– メソッドのパラメータに参照を渡す
– 未初期化で渡すと、NULLポインタを渡すことになる
19
実装側
例:outとref
呼出側
class clsParameterModifier
static void Main(string[] args)
{
// outの例
{
int i = 90, j= 30, k;
public void Add(int a, int b, out int ans){
// Add用
string s = "this is a pen.";// ChangeToUpperString用
ans = a + b;
Temp t = new Temp();// DispParams用
}
clsParameterModifier c = new
clsParameterModifier();
// refの例
public void ChangeToUpperString(ref string s){
// Addのチェック
s = s.ToUpper();
c.Add(i, j, out k);
}
// "out"と書きましょう
Console.WriteLine("90 + 30 = {0}.\n", k);
// paramsの例
// ChangeToUpperStringのチェック
public void DispParams(params object[] list){
Console.WriteLine("Before:{0}", s);
for(int i = 0; i < list.Length; i++){
c.ChangeToUpperString(ref s); // "ref"と書きましょう
if(list[i] is Temp){
Console.WriteLine("After:{0}", s);
Console.WriteLine("This is Temp.\n");
// DispParamsのチェック(可変化)
}else{
Console.WriteLine("This isn't Temp.\n");
c.DispParams(1,2,3,4,5,t);
}
}
}
}
}
20
namespace
•
•
•
•
•
独自クラスをグループ化する
作成したクラスなどを
複数のcsファイルをひとつのnamespaceにできる
namespace呼び出しには“using”を利用する
命名は慎重に・・・
– 利用しているnamespaceでクラスなどの名前が同一の
場合は、完全修飾名で指定
21
オブジェクト指向サポート
22
オブジェクト指向サポート
•
•
•
•
オブジェクト指向の基本
カプセル化
継承
ポリモーフィズム
23
オブジェクト指向の基本
• C#は、オブジェクト指向言語である
• オブジェクト指向の基本3要素
– カプセル化:オブジェクトの内部を隠す
– 継承:コードの再利用(“is-a”と“has-a”)
– ポリモーフィズム:目的のオブジェクトを動的に
利用する( “is-a” 時のみ可能)
24
カプセル化
• “readonly”キーワード
– 「読み込み」のみ可能
• プロパティ化
– “get”と“set”
– 静的プロパティ
• クラス単位で利用
• 普通のプロパティと同様に操作可能
• 静的コンストラクタ
– 静的メンバを初期化するために利用
– 可視性のキーワードを指定できない
25
継承 “is-a”
• “protected”キーワード
– メンバを子クラスからアクセス可能にする
• “base”キーワード
– ベースクラスのコンストラクタを呼ぶ
– デフォルトコンストラクタを呼ばないので、パフォーマン
ス向上
• “sealed”キーワード
– “is-a”継承を禁止する
– “has-a”継承は可能
26
例:“base”キーワード
ベースクラス
class Employee
サブクラス
class Manager : Employee
{
{
public int supNum;
public int EmpID;
/*
// ノーマルなコンストラクタ
public int Length;
public Manager(int SupNum, int empID, int Length)
public Employee(){}
{
public Employee(int empID, int length)
supNum = SupNum;
{
EmpID = empID;
EmpID = empID;
Length = Length;
Length = length;
}
*/
}
// "base"キーワードを利用したコンストラクタ
}
public Manager(int SupNum, int empID, int Length)
: base (empID, Length)
{
supNum = SupNum;
}
}
27
継承 “has-a”
• 外側のクラスを親クラス、含まれる側のクラスを
子クラスと呼ぶ
– “is-a”継承のベースクラス、サブクラスとの違いに注意
• 子クラスは“private”メンバとする
– カプセル化のため
• 子クラスの初期化は、親クラスのコンストラクタで
行うのが基本
• 子クラスへのアクセスは、親クラスでメソッドを実
装しておこなわれる(委譲)
28
ポリモーフィズム 1
• サブクラスでオーバーライドするメンバは
“public”で宣言する
• “base”キーワードを利用してデフォルトの
実装を呼び出し可能
• “new”キーワードで仮想メソッドの継承を
断ち切ることができる
– ベースクラスとメソッドが同名だが互換性が無
い場合に利用
29
“new”キーワード
•
Object
AbstractなDraw
メソッド
Shape
Squre
Drawメソッドの実装
Cube
Squre.Drawメソッ
ドを隠蔽した新しい
実装
左図のような継承を行うとき、「Cube」
クラスが上位クラスのメソッドを継承さ
せないようにするために、“new”キー
ワードを利用する
public class Cube : Squre
{
// 他の実装
…
// 継承されたメソッドを隠蔽する
public new void Draw()
{
// 実装
}
}
30
ポリモーフィズム 2
• “abstract”キーワードを利用してベースクラスの作
成を禁止する
abstract public class Shape
Shape s1 = new Shape();
{
=>コンパイルエラー!!不可
// 実装
}
このようにすることで、 Shapeクラスをインスタン
ス化させないようにする
• “abstract”キーワードを利用して“純粋仮想メソッ
ド”にすることで継承側で実装を強制する
31
インターフェース
32
インターフェース
• 概要
• 明示的な実装
• インターフェース参照の取得
33
インターフェース 概要
• データタイプを定義できない
• メソッドのデフォルト定義を実装できない
– 継承したクラスに実装を強制する
• 多重継承可能
– クラスでは無理
public class Triangle : Shape, Line <=コンパイルエラー!!
public class Triangle : IShape, ILine <=インターフェースなのでO.K.
34
インターフェース 明示的な実装
• 継承したインターフェース、またはクラスが
同じメソッド名を保有している場合に利用
• 以下のように実装する
public class : Shape, IShape
{
// これはShapeクラス
public override void Draw(){ ///実装 }
// これはIShapeインターフェース
// アクセス修飾子が必要ない
void IShape.Draw(){ ///実装 }
}
35
インターフェース 参照の取得
• インターフェースは、インターフェース型でキャス
トすれば直接参照可能
– クラスがインターフェースを継承していないと
InvalidCastException例外発生
• “as”でのキャスト
– クラスがインターフェースをサポートしていない場合は、
例外を起こさずNULLをセットする
• “is”を利用して互換性チェック可能
– if(“オブジェクト名” is “インターフェース名”)
36
Something1 s1 = new Something1();
例:“as”と“is”
public interface IShape
Something2 s2 = new Something2();
Something3 s3 = new Something3();
IShape i;
// 普通のキャスト
{
void Draw();
try{
i = (IShape)s2; // 例外発生
}
public abstract class Shape
}catch{
Console.WriteLine("The InvalidCastException occurs.");
{
public abstract void Draw();
}
// "as"を利用したキャスト
}
public class Something1 : IShape
i = s2 as IShape; // 例外は発生しない
if(i != null)
{
void IShape.Draw(){ Console.WriteLine("1"); }
{
Console.WriteLine("This class inheritances IShape.");
}
public class Something2 : Shape
}else{
Console.WriteLine("This class doesn't inheritances
IShape.");
{
public override void Draw(){ Console.WriteLine("2"); }
}
}
// "is"を利用した互換性チェック
public class Something3 : Shape, IShape
{
// s1,s3 => Yes, s2 => No
if(s1 is IShape){ // “true”か”false”が返される。ここは“true”。
void IShape.Draw(){ Console.WriteLine("3 for inter"); }
public override void Draw(){ Console.WriteLine("3 for class"); }
}
Console.WriteLine("Yes.");
37
}else{
Console.WriteLine("No.");
イベント/デリゲート
38
イベント/デリゲート
•
•
•
•
•
コールバック
デリゲートの定義
イベントとは?
イベントのリッスン
イベントのデザイン
39
コールバック
• C/C++で利用されていた技術
– 関数が他の関数に情報を返すときに利用
• 実体は「関数ポインタ」
• 欠点は、
– 呼び出し側に型情報を示せない
– タイプセーフにできない
• 関数名=型名
• この問題解決のため“デリゲート”が作られた
40
デリゲートの定義
• 実体は、関数ポインタをラップするクラス
• 登録する関数の戻り値、パラメータなどは自由
• 関数の実装は、同クラス/他クラスでも可
– Targetプロパティで、実装クラス名の取得可能
• 任意の数の関数を登録できる
– 内部的に関数ポインタのリンクがある
– “combine”または“+”演算子で追加可能
– “remove”で削除
41
イベントとは?
• 実行時に呼び出す関数を指定する方法
– 例外程深刻ではない障害が発生したときなど
に、処理する関数を呼び出すのに利用する
• イベント処理の手順
– “event”キーワードでイベントを定義
– イベント発生時に呼び出す関数を定義
• デリゲート関数を利用
42
イベントのリスニング
• イベントを定義したクラスを利用するときに
は、イベントハンドらとして定義されている
“delegate”メソッドを実装する
• オーバーロードされた演算子でイベントハ
ンドラを登録する
– “+=”:イベントハンドラに追加
– “ー=” :イベントハンドラから削除
43
例:イベントハンドラへの登録
// イベントを発生し、delegateメソッドも定義されいるクラス
// イベントハンドラを利用したコード
public class Line
// Lineオブジェクト作成
{
Line l = new Line();
public static int i;
// イベントをフックする
// イベント発生時に呼び出す関数(デリゲート関数)
Line.Erase += new Line.LineEventHandler(EventLine.OnErase);
// パラメータは"string"、戻り値は"void"
Line.Add += new Line.LineEventHandler(EventLine.OnAdd);
public delegate void LineEventHandler(string s);
Line.Uphold += new Line.LineEventHandler(EventLine.OnUphold);
// このクラスが発生させるイベント
// イベントを発生する
// public static event (定義したdelegateメソッド) 任意のイベント名
l.MakeEvent();
public static event LineEventHandler Erase;
// イベントを切り離す
public static event LineEventHandler Add;
Line.Erase -= new Line.LineEventHandler(EventLine.OnErase);
public static event LineEventHandler Uphold;
Line.Add -= new Line.LineEventHandler(EventLine.OnAdd);
// イベントを発生させるメソッド
Line.Uphold -= new Line.LineEventHandler(EventLine.OnUphold);
public void MakeEvent()
{// イベントを発生させる
Erase("Erase"); // "Erase"イベント発生
Add("Add"); // "Add"イベント発生
Uphold(“Uphold”); // “Uphold”イベント発生
}
}
44
イベントのデザイン
• イベント発生側
– イベントを処理する“delegate”メソッドを定義
– 発生するイベントをリストアップ
• イベント処理側
– 定義された“delegate”メソッドの型を確認
– 型に従い、イベントハンドラ用のクラス/イン
ターフェースを作成
– ハンドラの実装を行う
45
例外処理
46
例外処理
•
•
•
•
•
•
例外とは?
System.Exceptionクラス
try~catch~finally
“例外”のスロー
“using”ステートメント
“例外”の設計
47
例外とは?
• 既存のエラーコードの短所
– 処理できないイベント
• ランタイムエラー
• トラップ etc.
– エラーコードの多様化による統一性の欠如
• #define => WIN32 API
• HRESULT => COM etc..
• SEH(構造化例外処理)は、従来のエラー処理で
は対処できない障害を検出するための機能
48
System.Exceptionクラス
• .NET Frameworkでは、例外の実体は
Exceptionの継承オブジェクト
– System.Exceptionの主要なプロパティ
• StackTrace:
エラーが発生した位置を判別するときに利用
• InnerException:
「“例外”処理中に発生した/する例外」を処理する際に利用
元々の原因となった例外を格納する
49
例:“InnerException”
public class MyAppException:ApplicationException
public class ExceptExample
{
{
public MyAppException (String message) : base (message) {}
public void ThrowInner ()
// “Exception”クラスには“String”と
{
throw new MyAppException("ExceptExample inner exception.");
// "Exception"をパラメータに持つコンストラクタがある
public MyAppException (String message, Exception inner) :
}
base(message,inner) {} public void CatchInner() // “Main”でこの関数を呼ぶ
}
{
try {
this.ThrowInner(); //最初の例外をスロー
}catch (Exception e) {
// ここでの例外の原因は、上の"this.ThrowInner();"
// なので、InnerExceptionにはこの例外をスローする
// 元々の原因となった“e”を設定し、再スローする
throw new MyAppException("Error caused by trying ThrowInner.", e);
}
}
}
50
try~catch~finally
• 例外が発生するコードを“try”ブロックで囲む
– オブジェクトの生成
– 3rdパーティのクラスのメソッド呼び出し etc..
• “try”に対応する“catch”ブロックを記述
– 例外発生時、処理は“catch”に移動
– 発生しない場合は, “catch”ブロックは処理されない
• “finally”ブロックは必ず実行される
– オプションなので、作成は必須ではない
– オブジェクトのリリースなどの後処理を記述する
– 記述は、“using”ステートメントを考慮 => 後述
51
“例外”のスロー
• 例外がスローされるタイミング
– システムが例外を検出
• .NET Framework SDKにリストがある
– “throw”
• 任意のタイミングで例外を発生できる
• “catch”ブロック内で再スロー可能
– 呼び出し側の“catch”では再スローされた例外を処理
• “Exception”クラスを継承して、独自の例外
クラスを作成できる
52
“using”ステートメント
• “using”を利用すると、オブジェクトのクリー
ンアップを行う
– コンパイラが自動的に“try~catch”ブロックを
作成
– “finally”ブロック中で、“Dispose”メソッドを呼
び出す
– “Dispose”メソッドをサポートしていないオブ
ジェクトには利用できない
53
例:“using”ステートメント
“using” 未使用
“using” 使用
class app
{
…
try {
class app
{
…
using(Byte b = new Byte[]){
// 実装
}
}
Byte b = new Byte[];
// 実装
}
catch {
…
}
finally{
if(b != null)
((IDisposable)b).Dispose();
}
}
コンパイラは両方のコードを
まったく同じネイティブコード
にする
54
“例外”の設計
• これまで、例外処理は「パフォーマンスが悪くな
る」と言われていた
– 原因:
• 例外発生時、インスタンス化されたオブジェクトをクリアする
ため独自にトラップフレームを用意
=>そのため、“try”ブロックを狭くしていた
• .NETでは、GCがあるためトラップフレームを考
慮する必要なし
– “try”ブロックを広くできる
• “catch”ブロックは考慮できる例外ごとに記述
• “finally”ブロックでは、メモリ開放以外の後処理
– “using”ステートメント
55
GC
56
GC
•
•
•
•
概要
Finalizeメソッド
IDisposableインターフェース
ジェネレーション
57
GC 概要
• オブジェクトの有効期間
– “new”されたオブジェクトはヒープ領域に置かれる
– .NETランタイムがメモリ領域を管理
– ヒープ領域は、プロセスが存在する間は開放されない
• ヒープ領域を明示的に開放するために
– “Finalize”メソッド
– “IDisposable”インターフェース
58
GC概要
オブジェクト生存期間
メモリ管理機能
(メモリの確保・解放)
• メモリの確保や解放などは自
動で行う。
• アプリケーションでオブジェク
トを作成すると自動でメモリが
確保される。
管理ヒープ領域
59
GC概要
GCの動作
メモリ管理機能
(メモリの確保・解放)
メモリ管理機能
(メモリの確保・解放)
管理ヒープ領域
管理ヒープ領域
GC後
GC前
これらの領域を開放
:未参照領域
60
GC概要
GCの動作
• ヒープ上の全てのオブジェクトには、特定のジェ
ネレーションが設定されている
– 0:新たに配置されたオブジェクト
– 1:GCのスイープ後に残ったもの
– 2:GC後に残ったもの
• GCは、最初に「0」のものからスイープをはじめ、
十分にメモリを確保したらスイープを中止して次
のジェネレーションに昇進する
– このため、参照が無くてもメモリ上にオブジェクトが存
在することに注意
61
GC概要
GCタイミング
• 誰からも参照されていないオブジェクトは削
除される。
– しばらく実行していると“参照されているオブジェ
クト”と“誰からも参照されていないオブジェクト”
が混在する状況になる
– 参照されていないオブジェクトが削除される
• 削除するタイミングは全てGCに一任されて
いるが、一般的にはヒープ領域が不足してき
た時に行われる
62
GC Finalizeメソッド
• Finalizeメソッド = デストラクタ + GC機能
– “new”を使ってC#オブジェクトを作成すると、ラ
ンタイムは“Finalize”をサポートしているかを
チェックする
– サポート時は、オブジェクトを「ファイナライ
ゼーションキュー」に格納
• GC時、ランタイムはFinalizeメソッドをコール
• このオーバヘッドで、メモリからの開放のタイミング
が遅くなる
63
GC Finalizeメソッド
コード
Sample1 o1 = new Sample1();
Sample2 o2 = new Sample2();
Sample3 o3 = new Sample3();
GCが起動すると、ランタイム
はメモリを開放
Sample4 o4 = new Sample4();
マネージヒープ
o1 o2★ o3 o4★
Finalizeをサポート
すると、ランタイム
はマークをつけて
ヒープに格納する
GCがクリアするタイミングで
Finalizeをコール
o2
o4
ファイナライゼーション
キュー
64
GC IDisposable
• デストラクタでは、クリアのタイミングは呼
出側では制御できない
• .NETクラスライブラリは“IDisposable”イン
ターフェースを用意
– リソースの明示的な破棄をサポートする
– “Dispose”メソッド内では、“SuppressFinalize”メ
ソッドを呼び出すこと
• GC時、“Finalize”の呼び出しを行わなくなる
65
リフレクション
66
リフレクション
• 取得できる情報
• “Type”クラス
– クラスのフィールド、メソッド、プロパティなどの値を取
得
• “Reflection”クラス
• レイトバインディング
– “Activator”クラス
– COMのIDispatchインターフェースを取得するときに利
用
67
リフレクションの意義
• リフレクションの実体
– CLRをターゲットとする全モジュールが持つ「メ
タデータ」は、モジュールの情報をもつ
– リフレクションは、モジュール内のメタデータに
対するオブジェクトモデル
• リフレクションの利用シナリオ
– レイトバインディング時に、利用するアセンブリ
の型をチェック
– アセンブリの全モジュールのメタデータを調査
68
取得できる情報 1
•
•
•
•
Assembly
– アセンブリを定義または読み込み
– アセンブリ マニフェストにリストされているモジュールを読み込み
– そのアセンブリから型を検索し、そのインスタンスを作成
Module
– モジュール内のクラスなどの情報
– グローバル メソッド、モジュールに定義されている固有の非グローバル
なメソッド
ConstructorInfo
– コンストラクタの実装詳細 (abstract または virtual など)
– 名前、パラメータ、アクセス修飾子 (public または private など)
– 特定のコンストラクタ呼び出し:Type オブジェクトの GetConstructors メ
ソッドまたは GetConstructor メソッド
MethodInfo
– 名前、戻り値の型、パラメータ、アクセス修飾子 (public または private な
ど)
– メソッドの実装詳細 (abstract または virtual など)
– 特定のメソッドを呼び出し:Type オブジェクトの GetMethods メソッドまた
69
は GetMethod メソッド
取得できる情報 2
•
•
•
•
FieldInfo
– フィールドの名前、アクセス修飾子 (public または private など)
– フィールドの実装詳細 (static など)
– フィールドの値を取得または設定
EventInfo
– 名前、イベント ハンドラのデータ型、カスタム属性、宣言型、イベントのリ
フレクションされた型
– イベント ハンドラを追加および削除
PropertyInfo
– プロパティの名前、データ型、宣言型、リフレクションされた型、読み取り
専用または書き込み可能のステータスなどの情報を探索
– プロパティの値を取得または設定
ParameterInfo
– パラメータの名前、データ型、パラメータが入力パラメータか出力パラ
メータかなどの情報を探索
70
– メソッド シグネチャ内のパラメータの位置を探索
“Type”クラス
• 実行時にクラスの情報を取得するための方法
– “GetType”メソッドで取得
• 取得できる情報
–
–
–
–
メソッド
インターフェース
プロパティ
取得された値のタイプをチェックするメソッドもある
• IsAbstract,IsArray,etc…
• 取得される情報は配列で返される
71
“Reflection”クラス
• “Assembly”クラス
– アセンブリを動的にロードする
• Load(“名前空間”)
• LoadFrom(“モジュールのフルパス”)
– 識別子はアセンブリの名前空間
• クラスの情報と同様に情報を列挙できる
• 指定アセンブリ内の指定クラスのメンバ情
報も取得できる
72
例:“GetType”
// Typeを列挙
public void AllTypeList(Assembly a)
{
Type[] types = a.GetTypes();
foreach(Type t in types)
Console.WriteLine("Type = {0}", t);
}
// 指定メソッドを表示
public void AllMemberList(Assembly a)
{
// SampleTypeタイプを取得
•左の例では、
“ConsoleApplication1”内に
“SampleType”クラスが存在する
•クラス内のメソッドは、
“GetMethod”および“Invoke”を
利用して呼び出す
Type type = a.GetType("ConsoleApplication1.SampleType");
// SampleTypeを作成する
object obj = Activator.CreateInstance(type);
// メソッドの情報を取得
MethodInfo mi = type.GetMethod("SampleMethod");
// メソッドを呼び出す(パラメータなしの場合はnull)
mi.Invoke(obj, null);
}
73
レイトバインディング
• ほとんどのモジュールはアーリーバインディング
にするべき
– アーリーバインディング:コンパイル時にエラー検出
– レイトバインディング:実行時に自身が記述したコード
で整合性をチェックする
• “Activator”クラス
– “CreateInstance”メソッドでモジュール内の指定したク
ラスをインスタンス化
– “Invoke”メソッドを使って指定クラスのメソッドを呼び
出す
– 呼び出しメソッドがパラメータを持つ場合は,配列にし
74
て渡す
モジュール配布
75
モジュール配布 アジェンダ
• アセンブリ
– プライベート
– 共有
•
•
•
•
“config”ファイル
共有名(ストロングネーム)
バージョンポリシー
配布
76
アセンブリ
• 既存の“EXE”や“DLL”の.NET版
– バージョンやコレクションを自己記述している
– .NETでは、アセンブリが配布の単位となる
• アセンブリには、「プライベート」と「共有」の2種類
ある
– プライベートアセンブリの配布は「side by side」
– 共有アセンブリは、GACに配布
• ロケーション
– プライベートはconfigファイルで設定
– 共有はGACに配布
• GACの場所は“machine.config”で設定
77
.NET アプリケーションの構造
マニフェスト
A.Dll
メタデータ
MSIL
関連他ファイルの参照情報
タイプメタデータ
MSILのコード
B.dll
メタデータ
MSIL
モジュールがアプリと
同じフォルダにあれ
ば“プライベート”、
GACにあれば“共
有”
これらの場所を
“config”ファイルで指
定する
•アセンブリにマニフェストは一つ
•マニフェスト内に他アセンブリの参照情報を保持
•コンパイラの“/addmodule”フラグを指定して作成
78
“config”ファイル
• アプリケーションが利用するアセンブリを明示的
に指定する
• マシン全体の構成は“machine.config”ファイルで
設定する
• ファイル名は“アプリケーション名.config ”
– 利用するには“Assembly.cs”ファイルでバージョン指定
が必須
– “AssembluVersion”属性で指定
• デフォルトでは“1.0.*”なので、変更は必須
79
バージョンポリシー
• アプリケーションのバージョンはデフォルト
では未設定
– “AssemblyVersion”で設定する
• バージョンポリシー
メジャー
マイナー
互換性有り
リビジョン
ビルド
多分
互換性有り
QFE
メジャー、マイナーが異なると互換性なしとみなしバインドが失敗する
リビジョン番号だけ異なる場合は、動作保証なしだがバインド成功
ビルド番号だけ異なる場合は,互換性ありとみなしバインド成功
80
共有名(ストロングネーム)
• 共有アセンブリは、複数のアプリケーションから
利用可能
– GACに配置される
– GACの位置は、“machine.config”で設定
• 共有名付きアプリケーション作成方法
– “sn.exe”を利用して共有名を持つファイルを作成
– “Assembly.cs”ファイルで、“AssemblyKeyFile”属性を
共有名を保持するファイルパスに設定する
– “gacutil.exe”でGACにインストール
81
配布
• アセンブリのバージョンポリシーをしっかり決める
– 要素は“メジャー”、“マイナー”、“リビジョン”、“ビル
ド”
– “AssemblyVersion”属性でバージョンを設定
• “プライベート”なら、基本は“side-by-side”
– “config”ファイルを利用して配布を設定
• ロケーション(“privatePath”属性)
• “共有”なら、GACに配布
– キーを作成し、“snk”ファイルを関連付ける
– “config”ファイルを利用してバージョンによるリダイレ
クトも可(“bindingRedirect”属性)
82