これらは全て、MSILと呼ばれる中間コードへとコンパイルされる。
MSILへコンパイルされたアセンブリは、他の.NET言語から簡単に利用できる。
しかし、ある言語では実装されているが、ある言語では実装されていない機能がある。例えばC++やC#の「ポインタ」は、VB.NETでは利用できない。
全ての.NET言語がサポートしなければならない仕様を共通言語仕様(CLS)と呼ぶ。
CLSは、外部に公開する部分にだけ適用される。つまり、メソッド内の処理コードなどには関係ない。
先程挙げた「ポインタ」は、CLSに定義されていないため、実装されている言語とされていない言語が存在する。
クラスライブラリで公開しているクラスのメンバに、ポインタを返すメソッドがあったとする。ポインタはCLSに定義されていないため、このメソッドは、CLSに準拠していないメンバとなる。当然VB.NETからこのメンバを利用することはできない。
クラスライブラリを開発する際に、開発言語とは異なる言語からの利用が想定される場合、クラスライブラリをCLS準拠にする必要がある。
CLSに準拠させるには、当然、公開する箇所がCLSの規定に従っている必要がある。ただし、それだけではなく、CLS準拠であることを明示的に示さなければならない。
CLS準拠であることを明示的に示すには、CLSCompliantAttributeを用いる。
CLSCompliantAttributeは、アセンブリ、型、メンバに対して有効であり、アセンブリに対して(通常、AssemblyInfo.csに)
[assembly: System.CLSCompliant(true)]
を付加することで、アセンブリに含まれる全ての型、メンバがCLS準拠であると示したことになる。
CLS非準拠な型やメンバが含まれている場合は、個別に
[System.CLSCompliant(false)]
を付加することで、部分的にCLS非準拠を示せる。
なお、.NET Frameworkの主要クラスライブラリであるmscorlibも、ほとんどの型はCLSに準拠しているが、UInt32構造体など、一部CLSに準拠していない型が含まれている。
これらのトランザクション実装は、MSDTCが起動されていないと正常に動作しない。
MSDTCは Distributed Transaction Coordinator という名前でWindowsサービスに登録されている。
MSDTCが起動されていない場合は、以下のようにしてMSDTCが自動で起動するよう設定する。
- [ コントロール パネル ] - [ 管理ツール ] - [ サービス ] を開く。
- サービスの [ Distributed Transaction Coordinator ] という項目を右クリックし、プロパティを開く。
- [ 全般 ]タブの中にある [ スタートアップの種類 ] を [ 自動 ] に変更する。
- [ 開始 ] ボタンをクリックする。
- [ OK ] ボタンをクリックする。
これで正常にトランザクション処理が行われる。
また、SQL Server 2005のドキュメントの [ 2.5.3 Windows で MS DTC が一部無効になっている ] という項目を見ると、MS DTCを完全に有効にする手順が記載されている。
分散トランザクションを使用するリンク サーバー、分散クエリ、およびリモート ストアド プロシージャが、この問題の影響を受ける場合があります。
このような問題を回避するには、SQL Server 2005 がインストールされているサーバーで MS DTC を完全に有効にする必要があります。
と書いてあるので、そういう問題に遭遇した場合は完全に有効にすればいい(遭遇しなきゃしなくていい)ってことかな。たぶん。
テキストファイルやXMLファイルなど、全てのファイルはアセンブリに埋め込んで利用することができる。
ファイルをアセンブリに埋め込むには、ファイルのプロパティ項目の [ ビルド アクション ] を、 " 埋め込まれたリソース " に設定してビルドする。
埋め込まれたリソースを利用するには、以下のようにリフレクションを利用する。
埋め込まれたリソース"Hoge.txt"を取得する例
using System;
using System.IO;
using System.Reflection;
namespace YokoKen.Sample
{
static class Program
{
void Main()
{
string outputText;
Assembly thisAssembly = Assembly.GetExecutingAssembly();
using (Stream resourceStream = thisAssembly.GetManifestResourceStream("YokoKen.Sample.Hoge.txt"))
{
using (StreamReader resourceReader = new StreamReader(resourceStream))
{
outputText = resourceReader.ReadToEnd();
}
}
Console.WriteLine(outputText);
Console.ReadLine();
}
}
}
注意すべきは、AssemblyオブジェクトのGetManifestResourceStreamメソッドに渡すファイル名には、名前空間を含める必要があるということだ。この名前空間はプロジェクトのプロパティ項目の [ 規定の名前空間 ] に設定してある名前空間(サブディレクトリに配置した場合、これにディレクトリ階層が加えられた名前空間)である。
Visual Studio 2005 SDK version 3.0 により、Visual Studio 2005(Express Editionを除く)でIronPython1.0によるIronPython開発を行うことができる。
ダウンロード
Download details: Visual Studio 2005 SDK version 3.0
まず、前提条件としてVisual Studio 2005(Express Editionを除く)がインストールされている必要がある。
Visual Studio 2005 SDK version 3.0をインストールしたら、まずはVisual Studio 2005を起動して、
[ C:\Program Files\Visual Studio 2005 SDK\2006.09\VisualStudioIntegration\Samples\IronPythonIntegration ] にある、
[ IronPython.sln ] を開く。
次にこのソリューションをビルド&実行する。すると、Visual Studio 2005がもう一つ起動される。
これで、完了。(Visual Studioが二つ起動されちゃってるので、一度両方とも閉じよう)
以降、スタートメニューの [ Visual Studio 2005 SDK ] - [ 2006.09 ] - [ Start Visual Studio 2005 under Experimental hive ] から起動、または [ ファイル名を指定して実行 ] で [ devenv /rootsuffix Exp ] と入力して実行すれば、拡張されたVisual Studio 2005でIronPython開発ができる。
導入の詳細はこちら(英語)
Aaron Marten's WebLog : A bit more on IronPython
IronPythonに関する情報はこちら(英語)
IronPython
大きく分けると明示的なトランザクションと暗黙的なトランザクションに分かれる。
明示的なトランザクションはトランザクションの開始,コミット,ロールバックを明示的に行う管理方法。トランザクションの開始、終了が明確に決まる。
暗黙的なトランザクションはトランザクションの開始,コミット,ロールバックが暗黙的に行われる管理方法。既にトランザクションが開始されていたらそのトランザクションに参加(便乗)する、といったことが可能。
以下に、.NET Frameworkでのトランザクション実装方法を挙げる。
【 従来からあるトランザクション実装方法 】
従来からある方法として、データベーストランザクション,手動トランザクション,自動トランザクションがある。
[ データベーストランザクション ]
ストアドプロシージャ内でのトランザクション処理。
SQL Server 2005 なら、SQL CLRにより、C#やVB.NETなどの.NET言語で実装できる。
@IT:.NETエンタープライズWebアプリケーション開発技術大全 3.2 データベーストランザクション
データベース エンジンの .NET Framework プログラミング
[ 手動トランザクション ]
ADO.NETが提供する、明示的なトランザクション処理。
トランザクションの実行
@IT:.NETエンタープライズWebアプリケーション開発技術大全 3.3 マニュアルトランザクション
SqlTransaction クラス (System.Data.SqlClient)
OracleTransaction クラス (System.Data.OracleClient)
DbTransaction クラス (System.Data.Common) (.NET Framework2.0で新しく追加された。)
[ 自動トランザクション ]
COM+を利用した、暗黙的なトランザクション処理。
COM+を利用するには、ServicedComponentクラスを継承させる。また、アセンブリを厳密名で署名し、サービスコンポーネントとして登録する必要がある。
自動トランザクションと .NET Framework クラス
方法 : .NET Framework クラスで自動トランザクションを使用する
サービス コンポーネントの作成
@IT:.NETエンタープライズWebアプリケーション開発技術大全 3.4 自動トランザクション
System.EnterpriseServices 名前空間
ServicedComponent クラス (System.EnterpriseServices)
TransactionAttribute クラス (System.EnterpriseServices)
【 .NET2.0から提供される、System.Transactions名前空間 】
.NET2.0では、新しくSystem.Transactions名前空間(System.Transactions.dll)が追加された。主なクラスとして、明示的なトランザクションを提供するCommittableTransactionクラスと、暗黙的なトランザクションを提供するTransactionScopeクラスがある。
TransactionScopeの方が手軽で、CommittableTransactionよりもTransactionScopeを使用すべきである。
トランザクション アプリケーションの作成
System.Transactions で提供される機能
.NET Framework 2.0 の System.Transactions について
トランザクション管理の昇格
System.Transactions 名前空間
[ CommittableTransactionによる明示的なトランザクション ]
明示的なトランザクション処理。CommittableTransactionよりもTransactionScopeを使用すべき。
CommittableTransaction を使用した明示的なトランザクションの実装
CommittableTransaction クラス (System.Transactions)
Transaction クラス (System.Transactions)
[ TransactionScopeによる暗黙的なトランザクション ]
COM+による自動トランザクションよりも遥かに容易に実現できる、暗黙的なトランザクション処理。
トランザクション スコープを使用した暗黙的なトランザクションの実装
10 行でズバリ !! TransactionScope の利用 (C#)
Enterprise Service および COM+ トランザクションとの相互運用性
TransactionScope クラス (System.Transactions)
TransactionScopeOption 列挙体 (System.Transactions)
基本はクラス ライブラリ開発のデザイン ガイドラインに従うとして、それ以外の範囲で俺的な規約。
[ 俺規約 ]
フィールドの初期化はフィールドの定義時ではなく全てコンストラクタで行う。
[ 理由 ]
・フィールドの定義と一緒に初期化しても、その後コンストラクタで更に初期化される可能性があるから。(読みづらい上に、無駄。)
・あるフィールドでは定義と一緒に初期化して、あるフィールドでは定義で初期化せずコンストラクタで初期化してじゃ読みづらい。
[ 補足 ]
静的フィールドも同様に静的コンストラクタで初期化する。
静的フィールドは、定義時に初期化し、静的コンストラクタを明示的に宣言しないこと。
詳細はこちらの記事を参照。
オブジェクトのメモリは、そのオブジェクトがアクセス可能である限り、回収されることはない。オブジェクトがアクセス不可能になるとオブジェクトのメモリはGCの対象となり、適切なタイミングでGCが回収してくれる。
変数(フィールドやらローカル変数やら)に格納されている参照のことを「強い参照」と言う。
「アクセス可能なオブジェクト」とは、強い参照が存在するオブジェクトのことを言う。ただし、その強い参照を所持しているオブジェクトもアクセス可能なオブジェクトである必要がある。つまり、強い参照を所持しているオブジェクトを辿って行くとアクセス不可能なオブジェクトに辿り着く場合、それらは全てアクセス不可能なオブジェクトである。また、実際にアクセスされている最中(コンストラクタ実行中だったりメソッド実行中だったり)のオブジェクトも、アクセス可能なオブジェクトである。
冒頭でも書いたとおり、アクセス可能なオブジェクトはGCの対象にはならない。
しかし、「強い参照」が存在せず「弱い参照」が存在するオブジェクトなら、弱い参照を通して呼び出すことができる上、GCの対象となる。
「弱い参照」とは、WeakReferenceクラスによる参照である。WeakReferenceは、コンストラクタで対象オブジェクトを受け取る。WeakReferenceオブジェクトのTargetプロパティを通して対象オブジェクトにアクセスできるのだが、WeakReferenceオブジェクトは、内部に強い参照を保持するのではなく、参照をIntPtr構造体として保持している。これにより、対象オブジェクトはGCの対象となる。
対象オブジェクトがGCの対象となるので、GCによって対象オブジェクトのメモリが回収された場合は、Targetプロパティはnull参照を返す。そのため、対象オブジェクトにアクセスする際は、Targetプロパティから強い参照を取得して、強い参照を通してアクセスする必要がある。
具体的には、まずTargetプロパティを変数に代入して強い参照を取得する。そして、その変数の値がnull参照であった場合は、再び対象オブジェクトを生成する。その後、その変数を通して対象オブジェクトにアクセスし、最後に強い参照を消去する(変数にnull参照を代入したり、ローカル変数ならスコープ外に処理が移れば勝手に消える)。
弱い参照の作成・使用の例
class Piyo
{
// Hogeオブジェクトへの弱い参照
private WeakReference weakHoge;
// コンストラクタ
public Piyo()
{
Hoge hoge = this.CreateHoge();
this.weakHoge = new WeakReference(hoge);
hoge = null;
}
// Hogeオブジェクトを使うメソッド
public void UseHoge()
{
Hoge hoge = (Hoge)this.weakHoge.Target;
if (hoge == null)
{
hoge = this.CreateHoge();
this.weakHoge.Target = hoge;
}
//
// Hogeを使った処理
//
hoge = null;
}
// Hogeオブジェクトを生成するメソッド
private Hoge CreateHoge()
{
Hoge hoge = new Hoge();
hoge.Name = "ほげ"
return hoge;
}
}
IsAliveプロパティを使って、対象オブジェクトがGCに回収されているかどうかを調べたり、直接Targetプロパティとnullを比較することもできるが、これらのプロパティにアクセスした時は回収されていなくても、直後に回収されてしまうというケースもありえる。なので、上記の例のように最初にTargetプロパティから強い参照を取得する必要がある。(強い参照の取得さえちゃんとすれば、IsAliveやTargetとの比較を用いても問題ない。)
弱い参照を使用するシーンとしては、サイズの大きなオブジェクトを保持して利用する際に、そのオブジェクトが常にメモリを占有してしまうよりは、GCの対象としておき、回収された場合は再び作成するという手段を取った方が、作成にかかるコストを考慮しても有益だという場合などである。
IronPythonは、.NET Framework上で動く動的型付け言語で、コンソールでの対話形式プログラミングが可能。
IronPython 1.0 は.NET Framework 2.0に対応している。
あと、こことかみると、UpdateRuleに「重ねて表示」を設定すると参照先の更新で削除されると書いてあるが、削除ではなく更新がされる。(参照先のキーの列が一意キーでnull許可していて、そこにnullを設定した場合は削除されるけど。)