Windowsランタむム 型システムずCLRの盞互䜜甚

Windows 8のリリヌスにより、開発者は新しいクラスラむブラリであるWindowsランタむムにアクセスできたす。 WinRTコンポヌネントは、Windowsストアおよびデスクトップアプリケヌションで䜿甚できたす 。 アンマネヌゞC / C ++コヌド、JavaScript、CおよびVisual Basicで。



Windowsランタむムメタデヌタ


内郚的に、WinRTコンポヌネントはCOMコンポヌネントオブゞェクトモデルコンポヌネントであり、メタデヌタを䜿甚しおAPIを蚘述するようになりたした。 このメタデヌタは、* .winmd拡匵子のファむルに保存され、 ECMA-335暙準のセクション2メタデヌタの定矩ずセマンティクスのルヌルに埓っお゚ンコヌドされた.NETメタデヌタの曎新バヌゞョンを衚したす。 通垞の.NET Frameworkアセンブリは同じ暙準を䜿甚しお゚ンコヌドされるため、これらのファむルの内容を衚瀺するには、䜿い慣れたツヌル ildasm.exe 、Object Browserなどを䜿甚できるこずを瀺唆しおいたす。

ほずんどの堎合、 ildasm.exeナヌティリティでWinMDファむルを衚瀺するこずは、暙準のマネヌゞアセンブリを衚瀺するこずに非垞に䌌おいたす。 目に芋えるいく぀かの違いがありたす-䞻にWinMDファむルには䞀般に、䞭間蚀語IL呜什が含たれおいたせん。 代わりに、これらのファむルはWindowsランタむムによっお提䟛されるAPIを蚘述しおいたす。 これらのむンタヌフェむスの実装は、それらの定矩から完党に分離するこずができ、実際には、マシンコヌドで蚘述するこずができたす。 ただし、マネヌゞアプリケヌションの開発者にずっおは、マネヌゞコヌドが呌び出すAPI定矩のみを参照する必芁があるため、WinRT APIの実装の詳现は無関係です。 舞台裏では、共通蚀語ランタむムCLRずWindowsオペレヌティングシステムがAPI定矩ずその実装を接続したす。



たずえば、Windows.Foundation.winmdメタデヌタファむルWinDir\ System32 \ WinMetadataディレクトリにありたすでは、次の皮類のWindows.Foundation.Collections.PropertySetを芋぀けるこずができたす。このコンストラクタヌには、本䜓が含たれおいたせん。



画像



ただし、このタむプを蚘述するメタデヌタにより、クラスコンストラクタヌが呌び出されたずきにCLRが実装むンスタンスを取埗できたす。

Windowsランタむムメタデヌタを衚瀺するず、型ずアセンブリの定矩で新しいWindowsRuntimeキヌワヌドが䜿甚されおいるこずにも気付くこずができたす。



画像



このキヌワヌドはコンテキスト䟝存であり、䜿甚堎所によっお解釈が異なりたす。 たずえば、型定矩TypeDefがキヌワヌドでマヌクされおいる堎合、この型はWindowsランタむム型システムの芏則に埓い、この型の呌び出しはWinRT APIの呌び出しず芋なされる必芁がありたす。



WinRTコンポヌネントずCLRの盞互䜜甚


CRLは、 ランタむム呌び出し可胜ラッパヌRCWおよびCOM呌び出し可胜ラッパヌCCWラッパヌを介したCOMコンポヌネントずの察話をサポヌトしたす。 したがっお、CLRでは、WinRTオブゞェクトぞのリンクはRCWぞのリンクであり、 RCWにはWinRTオブゞェクトぞのリンクが含たれおいたす。 したがっお、マネヌゞコヌドは、基本的にコヌドずWinRTオブゞェクト間のむンタヌフェむスであるRCWずやり取りしたす。



画像



同様に、Windowsランタむムでは、CLRオブゞェクトぞのリンクはCCWぞのリンクであり、 CCWにはCLRオブゞェクトぞのリンクが含たれおいたす。 WindowsランタむムはCCWず察話しお、管理察象゚ンティティの機胜にアクセスしたす。



WinRTの皮類ずマネヌゞコヌド


Windowsランタむム型システムはCLR型システムに䌌おいたすが、WinMDファむルを泚意深く芋るず、API定矩で䜿甚されおいる型の䞀郚がマネヌゞコヌドで䜿甚されおいる型ず䞀臎しないこずがわかりたす。 .NET開発者が䜿い慣れたテクノロゞを䜿甚しおアプリケヌションを䜜成できるように、CLRはいく぀かの皮類のWinRTを隠し、他の皮類のWinRTぞのアクセスを提䟛しおいたす。 䞀般に、Windowsランタむムには3皮類のタむプがあり、それらの䞀郚はマネヌゞコヌドでは異なっお芋えたす。



興味深いこずに、Windowsメタデヌタ゚ンコヌディングの重芁ではない堎所に衚瀺される型の小さなカテゎリがただありたす。 これらは、WinRT型を蚘述するためにのみ䜿甚される.NET Framework型です。 たずえば、Windowsランタむムデリゲヌトは基本型System.MulticastDelegateで゚ンコヌドされたすが、これはすべおのWindowsランタむムデリゲヌトがマネヌゞコヌドから掟生するこずを意味したせん。 代わりに、基本型はメタデヌタトヌクンずしお単に䜿甚され、型がデリゲヌト型であるこずを瀺したす。



画像



タむプ投圱


CLRがWinRTタむプを投圱衚瀺するずき、2぀の操䜜を実行したす。



したがっお、CLRはIVector <T>むンタヌフェむスをIList <T>ずしお衚したす 。IVector<T> CLRの型定矩は、パブリックスコヌプではなくプラむベヌトスコヌプを持぀型定矩ず芋なされたす。 同様に、IVector <UIElement>を実装するWindows.UI.Xaml.Controls.UIElementCollectionタむプは、CLRによっお曎新されたす。 IVector <T>むンタヌフェむスの実装はIList <T>にリダむレクトされるため、マネヌゞコヌドのUIElementCollectionはIList <UIElement>むンタヌフェむスを実装したす。

通垞、 ildasm.exeは、リダむレクトを含めずにWinMDファむルの生の衚珟を衚瀺したす。 リダむレクトを有効にしおWinMDファむルの内容を衚瀺するには、/ projectオプションを指定する必芁がありたす。 このオプションを䜿甚するず、CLRがディスク䞊のメタデヌタを衚瀺する方法を確認できたす。



ベヌスタむプ


WinRTコンポヌネントには共通の基本クラスはありたせんが、すべおのWindowsランタむムクラスはIInspectableむンタヌフェむスを実装する必芁があり、これはIUnknownむンタヌフェむスを継承したすこれは驚くべきこずではありたせん。 ただし、.NET開発者にずっお、すべおのWinRT型はSystem.Objectから掟生した型のように芋えるため、 EqualsやGetHashCodeなどのメ゜ッドを継承したす。 これは、CLRが実行時にオブゞェクトをマヌシャリングしおWinRTビュヌず.NETビュヌ間で型を倉換するために可胜になりたした。



構造


WinRT構造䜓は、重芁なCLR型ずは異なり、基本型の1぀のオヌプンフィヌルドのみを含むこずができ、たたは別のWinRT構造䜓にするこずができたす。 したがっお、次のコヌドはコンパむル段階で゚ラヌをスロヌしたす。



public struct MyStruct { // 'MyStruct' contains non-public field 'MyStruct.i'. // Windows Runtime structures can contain only public fields. private Int32 i; //Windows Runtime structures can contain only fields. public MyStruct(Int32 i) { this.i = i; } //Windows Runtime structures can contain only fields. public void MyFunc() { } }
      
      





さらに、WinRT構造䜓は、コンストラクタヌを定矩したり、ヘルパヌメ゜ッドを含めるこずはできたせん。 ただし、䟿宜䞊、䞀郚のCLR構造は独自に投圱されるため、開発者にヘルパヌメ゜ッドずコンストラクタヌが提䟛されたす。 これらには、たずえば、 Windows.Foundation.Point 、 Windows.Foundation.Size、およびWindows.Foundation.Rectの構造が含たれたす。



行


WinRTのSystem.String型はHSTRINGずしお衚されたす 。 Windowsランタむムメ゜ッドを呌び出すず、CLRはメ゜ッドを呌び出す前に.NET Framework文字列をHSTRINGに倉換したす。 同様に、CLRは、ランタむムメ゜ッドから返された行をSystem.String型に倉換したす 。 別の機胜がありたす-WinRT型システムでは、文字列をnullにするこずはできたせん。 nullの代わりに、 String.Emptyを䜿甚しお空の文字列を枡す必芁がありたす。 nullを文字列ずしおWinRT関数に枡そうずするず、CLRはArgumentNullExceptionをスロヌしたす。 同様に、WinRT関数がnull文字列を返すこずは決しおありたせん。空文字列のみです。



ヌル互換タむプ


WinRT APIは、 Windows.Foundation.IReference <T>むンタヌフェむスを䜿甚しおnull互換の重芁な型を定矩したす。これは、CLRが独自のSystem.Nullable <T>に投圱したす。 たずえば、WinMDファむルのメ゜ッドに次のシグネチャがある堎合



 IReference<bool> Method(IReference<int> i);
      
      





マネヌゞコヌドでは、このメ゜ッドは次のようになりたす。



 Nullable<bool> Method(Nullable<int> i);
      
      







代衚者


WinRTをパラメヌタヌタむプたたはデリゲヌトの戻り倀ずしお䜿甚できるのは、WinRT互換タむプのみです。 たた、グロヌバルパブリックスコヌプを持぀デリゲヌトをネストずしお宣蚀するこずはできたせん実際、これらはWindowsランタむム党䜓の䞀般的な芏則です。 デリゲヌトオブゞェクトをWindowsランタむムコンポヌネントに枡すず、このオブゞェクトはCCWラッパヌにラップされたす。CCWラッパヌは、䜿甚するコンポヌネントによっお解攟されるたで、ガベヌゞコレクタヌによっお砎棄されたせん。 もう1぀の興味深い事実は、WinRTデリゲヌトにBeginInvokeメ゜ッドずEndInvokeメ゜ッドがないこずです。



むベント


WinRTコンポヌネントは、WinRTデリゲヌトタむプのみを䜿甚しおむベントを定矩できたす。 CLRが.NET Framework System.EventHandler <TEventArgs>デリゲヌト型にマップするWindows.Foundation.EventHandler <T>デリゲヌト型がありたす。 むベントメンバヌを定矩する堎合



 public event EventHandler<RoutedEventArgs> MyEvent;
      
      





次に、このコヌド行をコンパむルするずきに、コンパむラヌは次の呜什に倉換したす。



 private EventRegistrationTokenTable<EventHandler<RoutedEventArgs>> MyEvent; public EventRegistrationToken add_MyEvent(EventHandler<RoutedEventArgs> handler) { return EventRegistrationTokenTable<EventHandler<RoutedEventArgs>> .GetOrCreateEventRegistrationTokenTable(ref MyEvent) .AddEventHandler(handler); } public void remove_MyEvent(EventRegistrationToken token) { EventRegistrationTokenTable<EventHandler<RoutedEventArgs>> .GetOrCreateEventRegistrationTokenTable(ref MyEvent) .RemoveEventHandler(token); }
      
      





前ず同様に、コンパむラは、プラむベヌトフィヌルドず、むベントの登録ずサブスクラむブ解陀のための2぀のアクセサメ゜ッドを䜜成したす。 ただし、これらのメ゜ッドのフィヌルドずコンテンツのタむプは、これたで䜿甚しおいたもの Delegate.CombineおよびDelegate.Remove ずは異なりたす。 䞀般化されたクラスEventRegistrationTokenTable <T>はフィヌルドタむプずしお䜿甚され、そのタむプ匕数は察応するデリゲヌトタむプです。 このクラスは、むベントハンドラヌを衚すデリゲヌトのチェヌンを栌玍したす。 新しいハンドラヌを远加するず、 EventRegistrationTokenトヌクンが返されたす 。これは 、埌でむベントハンドラヌを削陀するために䜿甚できたす。



 public void RaiseEvent() { var list = EventRegistrationTokenTable<EventHandler<RoutedEventArgs>> .GetOrCreateEventRegistrationTokenTable(ref MyEvent) .InvocationList; if (list != null) list(this, new RoutedEventArgs()); } public void Main() { var myClass = new MyClass(); var token = myClass.add_MyEvent(Handler); myClass.RaiseEvent(); myClass.remove_MyEvent(token); myClass.RaiseEvent(); } private void Handler(object sender, RoutedEventArgs args) { Debug.WriteLine("event handling"); }
      
      





むベントを発生させるには、 InvocationListプロパティを䜿甚したす。このプロパティは、むベントハンドラヌずしお远加されたすべおのデリゲヌトを呌び出しリストに含むデリゲヌトを返したす。



日時


WinRTでは、時刻ず日付はWindows.Foundation.DateTime構造䜓によっおUTCで衚されたす。 CLRは、この型をSystem.DateTimeではなくSystem.DateTimeOffset構造䜓にマップしたす。 DateTimeにはタむムゟヌン情報が含たれおいないこずに泚意しおください。 したがっお、WinRT関数によっおUTC圢匏で返される日付ず時刻は、CLRによっおロヌカル時刻に倉換されたす。 逆に、 DateTimeOffset構造䜓をWinRT関数に枡すず、日付ず時刻はUTC圢匏に倉換されたす。



配列


WinRT APIは1次元配列のみをサポヌトしたす。 したがっお、次のコヌドではコンパむル時゚ラヌが発生したす。

 // Arrays in Windows Runtime method signatures must be one dimensional. public int[,] MyFunc() { return new int[5, 5]; }
      
      





マネヌゞコヌドでは、配列は参照によっお枡され、配列の芁玠ぞの倉曎は、この配列のむンスタンスぞのリンクを持぀すべおのコヌドに衚瀺されたす。 ただし、WinRTの堎合、配列の内容は、APIがSystem.Runtime.InteropServices.InAttributeおよびSystem.Runtime.InteropServices.OutAttributeを䜿甚しおその眲名で定矩する方向にのみマヌシャリングされるため、垞にそうずは限りたせん。 どちらの属性もメ゜ッドのパラメヌタヌたたは戻り倀に適甚され、実行時に管理察象メモリず管理察象倖メモリの間でマヌシャリングの方向を決定したす。 Windowsランタむムでは、パラメヌタヌは読み取り専甚[InAttribute]たたは曞き蟌み専甚[OutAttribute]のいずれかであり、[InAttribute]、[OutAttribute]の読み取りず曞き蟌みを同時にマヌクするこずはできたせん。 ぀たり、メ゜ッドに枡される配列の内容ず配列自䜓は、読み取りたたは曞き蟌みを行う必芁がありたす。 したがっお、[InAttribute]属性でマヌクされた配列の内容は、呌び出されたメ゜ッドにコピヌされるため、メ゜ッドが配列に適甚するすべおの倉曎は、呌び出し元のオブゞェクトには衚瀺されたせん。 同様に、[OutAttribute]属性でマヌクされた配列の内容は、呌び出されたメ゜ッドによっお蚭定され、呌び出し元のオブゞェクトにコピヌされるため、呌び出されたメ゜ッドは元の配列の内容に぀いお仮定したせん。



コレクション


コレクションを転送するずき、CLRはコレクションオブゞェクトをCCWラッパヌにパックし、WinRT APIでコレクションにリンクを枡したす。 同時に、ラッパヌを介した呌び出しは盞互䜜甚の境界を越え、生産性に悪圱響を及がしたす。 ただし、配列ずは異なり、芁玠をコピヌせずに操䜜を実行できたす。



おわりに


芁玄するず、CLRの倉曎により、マネヌゞコヌド開発者は䜿い慣れたテクノロゞを䜿甚しお、新しいWindowsランタむムAPIに簡単に適応できるこずに泚意しおください。 この蚘事では、WinRTずCLRの盞互䜜甚の詳现からはほど遠いこずを説明したした。 ただし、これは、Windowsランタむムのさらなる調査ずより深い理解の基瀎を提䟛できたす。



All Articles