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
© Copyright 2025 ExpyDoc