{"id":3641,"date":"2013-01-29T16:05:40","date_gmt":"2013-01-29T14:05:40","guid":{"rendered":"http:\/\/www.centigrade.de\/blog\/en\/?p=3641"},"modified":"2020-01-25T19:43:03","modified_gmt":"2020-01-25T18:43:03","slug":"from-windows-to-tiles-leveraging-reflection-to-inspect-and-contrast-wpf-with-winrt-xaml","status":"publish","type":"blog","link":"https:\/\/www.centigrade.de\/en\/blog\/from-windows-to-tiles-leveraging-reflection-to-inspect-and-contrast-wpf-with-winrt-xaml\/","title":{"rendered":"From windows to tiles: Leveraging reflection to inspect and contrast WPF with WinRT XAML"},"content":{"rendered":"<p>To begin with, our primal, simple aim was contrasting several concepts as applied in good old WPF with the way they have been implemented in WinRT . To actually enable a both exhaustive and reasonable comparison between both UI frameworks, we pragmatically decided to unleash some reflection functionality on the respectively affected assemblies.<!--more--> That being said, it turned out that scouring all eligible assemblies for usages of a certain type, let\u00b4s say ICommand, appears not to be as straight forward in a Windows Store app as it does in WPF. For instance, let\u00b4s assume we want to determine all occurrences of implementations of the ICommand interface within WPF; therefore, we require some functionality to examine all types being defined in WPF-related assemblies such as WindowsBase, PresentationCore and PresentationFramework. Taking a WPF project as granted, we may now exploit the .NET-Framework\u2019s capability to access the current application domain and simply iterate over all assemblies therein:<\/p>\n<pre class=\"csharpcode\" style=\"font-size: small; color: black; font-family: Consolas, 'Courier New', Courier, Monospace; background-color: #ffffff;\"><span class=\"kwrd\" style=\"color: #0000ff;\">private<\/span> IEnumerable&lt;Type&gt; SearchCurrentAppDomainForSubtypesOf(Type superType)\r\n        {\r\n            <span class=\"kwrd\" style=\"color: #0000ff;\">return<\/span> AppDomain\r\n                .CurrentDomain\r\n                .GetAssemblies()\r\n                .SelectMany(assembly =&gt; assembly.GetTypes())\r\n                .Where(type =&gt; superType.IsAssignableFrom(type));\r\n        } \r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Unfortunately, this approach proved to be desperately unsatisfactory in our Windows Store app as we could not access our application\u00b4s domain from within the WinRT API. Thus, we required a different strategy.<\/p>\n<p>Examining our Windows store app project\u00b4s structure in a bit more detail, we figured out that the VS-generated references linked to the \u201cWindows SDK\u201d that comes shipped as \u201cWindows.winmd\u201d and to a set of DLLs called \u201c.NET for Windows Store apps\u201d.<\/p>\n<p>Conveniently, the Windows.winmd is supplemented with an XML-formatted file (named \u201cWindows.xml\u201d) containing metadata of its types, properties and namespaces. Eventually, we decided to utilize this file by simply traversing its tree and successively reflecting any type contained.<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"csharpcode\" style=\"font-size: small; color: black; font-family: Consolas, 'Courier New', Courier, Monospace; background-color: #ffffff;\"><span class=\"kwrd\" style=\"color: #0000ff;\">private<\/span> async Task&lt;List&lt;Type&gt;&gt; SearchWindowsWinmdForSubtypesOf(Type superType, \r\n        StorageFile windowsXmlFile)\r\n        {\r\n            <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> result = <span class=\"kwrd\" style=\"color: #0000ff;\">new<\/span> List&lt;Type&gt;();\r\n \r\n            <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> document = await XmlDocument.LoadFromFileAsync(windowsXmlFile);\r\n            <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> xml = document.GetXml();\r\n            <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> xdoc = XDocument.Parse(xml);\r\n \r\n            <span class=\"kwrd\" style=\"color: #0000ff;\">foreach<\/span> (<span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> member <span class=\"kwrd\" style=\"color: #0000ff;\">in<\/span> xdoc.Descendants(<span class=\"str\" style=\"color: #a31515;\">\"member\"<\/span>))\r\n            {\r\n                <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> memberName = member.Attribute(<span class=\"str\" style=\"color: #a31515;\">\"name\"<\/span>).Value;\r\n \r\n                <span class=\"kwrd\" style=\"color: #0000ff;\">if<\/span> (memberName.ToUpper().StartsWith(<span class=\"str\" style=\"color: #a31515;\">\"T:\"<\/span>))\r\n                {\r\n                    <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> typeString = memberName.Substring(2);\r\n                    <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> type = Type.GetType(typeString + \r\n                        <span class=\"str\" style=\"color: #a31515;\">\", Version=255.255.255.255\"<\/span> +\r\n                        <span class=\"str\" style=\"color: #a31515;\">\", Culture=neutral\"<\/span> +\r\n                        <span class=\"str\" style=\"color: #a31515;\">\", PublicKeyToken=null\"<\/span> +\r\n                        <span class=\"str\" style=\"color: #a31515;\">\", ContentType=WindowsRuntime\"<\/span>);\r\n \r\n                    <span class=\"kwrd\" style=\"color: #0000ff;\">if<\/span> (superType.GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()))\r\n                    {\r\n                        result.Add(type);\r\n                    }\r\n                }\r\n            }\r\n            <span class=\"kwrd\" style=\"color: #0000ff;\">return<\/span> result;\r\n        }\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Similarly, we subsequently implemented a function to search the remaining DLLs that are collectively referred to as \u201c.NET for Windows Store apps\u201d. Even though these assemblies are available as plain old DLLs, we could not simply reflect them by parsing their file path as the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/1009fa28%28v=vs.110%29.aspx\">Assembly.LoadFrom(assemblyFile:String)<\/a> method does not exist anymore. Instead, we need an assembly\u00b4s full name to load it. Fortunately, we could find a further XML-file (\u201cFrameworkList.xml\u201d) in one of the referenced directory\u00b4s subfolders containing a list of all comprised assemblies including their full names. Finally, we used this file to iterate over all assemblies to extract their full names and to reflect them subsequently.<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"csharpcode\" style=\"font-size: small; color: black; font-family: Consolas, 'Courier New', Courier, Monospace; background-color: #ffffff;\"><span class=\"kwrd\" style=\"color: #0000ff;\">private<\/span> async Task&lt;List&lt;String&gt;&gt; SearchDotNetForWindowsStoreAppsForSubtypesOf(\r\n        Type superType, StorageFile frameworkListXmlFile)\r\n        {\r\n            <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> result = <span class=\"kwrd\" style=\"color: #0000ff;\">new<\/span> List&lt;String&gt;();\r\n \r\n            <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> document = await XmlDocument.LoadFromFileAsync(frameworkListXmlFile);\r\n            <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> xml = document.GetXml();\r\n            <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> xdoc = XDocument.Parse(xml);\r\n \r\n            <span class=\"kwrd\" style=\"color: #0000ff;\">foreach<\/span> (<span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> fileList <span class=\"kwrd\" style=\"color: #0000ff;\">in<\/span> xdoc.Descendants(<span class=\"str\" style=\"color: #a31515;\">\"FileList\"<\/span>))\r\n            {\r\n                <span class=\"kwrd\" style=\"color: #0000ff;\">foreach<\/span> (<span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> file <span class=\"kwrd\" style=\"color: #0000ff;\">in<\/span> xdoc.Descendants(<span class=\"str\" style=\"color: #a31515;\">\"File\"<\/span>))\r\n                {\r\n                    <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> name = file.Attribute(<span class=\"str\" style=\"color: #a31515;\">\"AssemblyName\"<\/span>).Value;\r\n                    <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> version = file.Attribute(<span class=\"str\" style=\"color: #a31515;\">\"Version\"<\/span>).Value;\r\n                    <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> culture = file.Attribute(<span class=\"str\" style=\"color: #a31515;\">\"Culture\"<\/span>).Value;\r\n                    <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> publicKeyToken = file.Attribute(<span class=\"str\" style=\"color: #a31515;\">\"PublicKeyToken\"<\/span>).Value;\r\n \r\n                    <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> fullName = name + \r\n                        <span class=\"str\" style=\"color: #a31515;\">\", Version=\"<\/span> + version + \r\n                        <span class=\"str\" style=\"color: #a31515;\">\", Culture=\"<\/span> + culture + \r\n                        <span class=\"str\" style=\"color: #a31515;\">\", PublicKeyToken=\"<\/span> + publicKeyToken;\r\n                    <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> assemblyName = <span class=\"kwrd\" style=\"color: #0000ff;\">new<\/span> AssemblyName(fullName);\r\n \r\n                    <span class=\"kwrd\" style=\"color: #0000ff;\">try<\/span>\r\n                    {\r\n                        <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> assembly = Assembly.Load(assemblyName);\r\n                        <span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> types = assembly.DefinedTypes;\r\n \r\n                        <span class=\"kwrd\" style=\"color: #0000ff;\">foreach<\/span> (<span class=\"kwrd\" style=\"color: #0000ff;\">var<\/span> type <span class=\"kwrd\" style=\"color: #0000ff;\">in<\/span> types)\r\n                        {\r\n                            <span class=\"kwrd\" style=\"color: #0000ff;\">if<\/span> (superType.GetTypeInfo().IsAssignableFrom(type))\r\n                            {\r\n                                result.Add(type.Namespace + <span class=\"str\" style=\"color: #a31515;\">\".\"<\/span> + type.Name);\r\n                            }\r\n                        }\r\n                    }\r\n                    <span class=\"kwrd\" style=\"color: #0000ff;\">catch<\/span> (Exception) { result.Add(<span class=\"str\" style=\"color: #a31515;\">\"Skipped \"<\/span> + fullName); }\r\n                }\r\n            }\r\n            <span class=\"kwrd\" style=\"color: #0000ff;\">return<\/span> result;\r\n        }\r\n<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"author":29,"featured_media":0,"template":"","tags":[249,210,247,214,192],"class_list":["post-3641","blog","type-blog","status-publish","hentry","tag-windows-store-app-reflection","tag-winrt","tag-winrt-reflection","tag-winrt-vs-wpf","tag-wpf-vs-rt"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.centigrade.de\/en\/wp-json\/wp\/v2\/blog\/3641","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.centigrade.de\/en\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/www.centigrade.de\/en\/wp-json\/wp\/v2\/types\/blog"}],"author":[{"embeddable":true,"href":"https:\/\/www.centigrade.de\/en\/wp-json\/wp\/v2\/users\/29"}],"version-history":[{"count":0,"href":"https:\/\/www.centigrade.de\/en\/wp-json\/wp\/v2\/blog\/3641\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.centigrade.de\/en\/wp-json\/wp\/v2\/media?parent=3641"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.centigrade.de\/en\/wp-json\/wp\/v2\/tags?post=3641"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}