Skip to content
This repository has been archived by the owner on Sep 14, 2018. It is now read-only.

Commit

Permalink
Experimetning with IInspectable
Browse files Browse the repository at this point in the history
  • Loading branch information
tmat committed Dec 2, 2012
1 parent 7c536e3 commit 60f24c3
Showing 1 changed file with 258 additions and 0 deletions.
258 changes: 258 additions & 0 deletions Hosts/WindowsStore/IronApp/MainPage.xaml.cs
@@ -1,9 +1,15 @@
using IronRuby;
using Microsoft.Scripting.Hosting;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using Windows.Foundation;
using Windows.UI.Text;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
Expand All @@ -13,6 +19,24 @@

namespace IronApp
{

public enum TrustLevel
{
BaseTrust = 0,
PartialTrust = 1,
FullTrust = 2
}

[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90")]
public interface IInspectable
{
void GetIids(out int iidCount, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)]out Guid[] iids);
void GetRuntimeClassName([MarshalAs(UnmanagedType.HString)]out string winTypeName);
void GetTrustLevel(out TrustLevel trustLevel);
}

/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
Expand Down Expand Up @@ -47,6 +71,240 @@ p box.text_alignment
InputBox.IsSpellCheckEnabled = false;
OutputBox.IsSpellCheckEnabled = false;
InputBox.Document.SetText(TextSetOptions.None, outputText);

// http://msdn.microsoft.com/en-us/library/windows/apps/br211377.aspx

IInspectable insp = (IInspectable)InputBox.Document;
string winTypeName;
insp.GetRuntimeClassName(out winTypeName);
Guid[] iids;
int iidCount;
insp.GetIids(out iidCount, out iids);

// winTypeName = "Windows.Foundation.Collections.IIterator`1<Windows.Foundation.Collections.IMapView`2<Windows.Foundation.Collections.IVector`1<String>, String>>";

var parts = ParseWindowsTypeName(winTypeName);
Type type = MakeWindowsType(parts);
var guid = type.GetTypeInfo().GUID;
}

private static char[] nameTerminators = new[] { '`', '>', ','};

internal static class WinRT
{
[DllImport("WinTypes")]
public static extern void RoParseTypeName(
[MarshalAs(UnmanagedType.HString)]string typename,
out int partsCount,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]out IntPtr[] typeNameParts);
}

private static string[] ParseWindowsTypeName(string name)
{
int partCount;
IntPtr[] partPtrs = null;
string[] parts;
try
{
WinRT.RoParseTypeName(name, out partCount, out partPtrs);

parts = new string[partPtrs.Length];
for (int i = 0; i < partPtrs.Length; i++)
{
parts[i] = WindowsRuntimeMarshal.PtrToStringHString(partPtrs[i]);
}
}
finally
{
if (partPtrs != null)
{
for (int i = 0; i < partPtrs.Length; i++)
{
if (partPtrs[i] != null)
{
WindowsRuntimeMarshal.FreeHString(partPtrs[i]);
}
}
}
}

return parts;
//List<string> parts = new List<string>();
//int position = 0;
//ParseWindowsTypeName(name, ref position, ref parts);
//return parts.ToArray();
}

private static void ParseWindowsTypeName(string name, ref int position, ref List<string> parts)
{
int i = name.IndexOfAny(nameTerminators, position);
if (i == -1)
{
parts.Add(name.Substring(position));
position = name.Length;
return;
}

if (name[i] != '`')
{
parts.Add(name.Substring(position, i - position));
position = i;
return;
}

i++;
while (name[i] >= '0' && name[i] <= '9')
{
i++;
}

parts.Add(name.Substring(position, i - position));

if (i == name.Length || name[i] != '<')
{
position = i;
return;
}

// parameters:
position = i + 1;
while (true)
{
ParseWindowsTypeName(name, ref position, ref parts);
if (position == name.Length || name[position] != ',')
{
break;
}

while (name[++position] == ' ')
{
}
}

Debug.Assert(name[position] == '>');
position++;
}

private static Type MakeWindowsType(string[] parts)
{
int i = 0;
return MakeWindowsType(parts, ref i);
}

private static Type MakeWindowsType(string[] parts, ref int i)
{
Debug.Assert(parts.Length > 0);
Type type = GetWindowsType(parts[i++]);
var info = type.GetTypeInfo();
if (!info.IsGenericTypeDefinition)
{
return type;
}

var args = new Type[info.GenericTypeParameters.Length];
for (int j = 0; j < args.Length; j++)
{
args[j] = MakeWindowsType(parts, ref i);
}

return type.MakeGenericType(args);
}

private static Type GetWindowsType(string name)
{
return GetPrimitiveWindowsType(name) ??
ProjectWindowsType(name) ??
Type.GetType(name + ", Windows, ContentType=WindowsRuntime");
}

private static Type GetPrimitiveWindowsType(string name)
{
switch (name)
{
case "Boolean": return typeof(System.Boolean);
case "Byte": return typeof(System.Byte);
case "Char": return typeof(System.Char);
case "Char16": return typeof(System.Char);
case "DateTime": return typeof(System.DateTimeOffset);
case "Double": return typeof(System.Double);
case "Guid": return typeof(System.Guid);
case "Int16": return typeof(System.Int16);
case "Int32": return typeof(System.Int32);
case "Int64":return typeof(System.Int64);
case "Object": return typeof(System.Object);
case "Single": return typeof(System.Single);
case "String": return typeof(System.String);
case "TimeSpan": return typeof(System.TimeSpan);
case "UInt8": return typeof(System.Byte);
case "UInt16": return typeof(System.UInt16);
case "UInt32": return typeof(System.UInt32);
case "UInt64": return typeof(System.UInt64);
case "Uri": return typeof(System.Uri);
case "Void": return typeof(void);
default:
return null;
}
}

private static Type ProjectWindowsType(string name)
{
switch (name)
{
case "Windows.Foundation.Collections.IIterable`1":
return typeof(IEnumerable<>);

case "Windows.Foundation.Collections.IVector`1":
return typeof(IList<>);

case "Windows.Foundation.Collections.IVectorView`1":
return typeof(IReadOnlyList<>);

case "Windows.Foundation.Collections.IKeyValuePair`2":
return typeof(KeyValuePair<,>);

case "Windows.Foundation.Collections.IMap`2":
return typeof(IDictionary<,>);

case "Windows.Foundation.Collections.IMapView`2":
return typeof(IReadOnlyDictionary<,>);

case "Windows.Foundation.Metadata.AttributeUsageAttribute":
return typeof(AttributeUsageAttribute);

case "Windows.Foundation.Metadata.AttributeTargets":
return typeof(AttributeTargets);

case "Windows.Foundation.EventHandler`1":
return typeof(EventHandler<>);

case "Windows.Foundation.EventRegistrationToken":
return typeof(EventRegistrationToken);

case "Windows.Foundation.HResult":
return typeof(Exception);

case "Windows.Foundation.IReference`1":
return typeof(Nullable<>);

case "Windows.Foundation.TimeSpan":
return typeof(TimeSpan);

case "Windows.UI.Xaml.Data.INotifyPropertyChanged":
return typeof(INotifyPropertyChanged);

case "Windows.UI.Xaml.Data.PropertyChangedEventHandler":
return typeof(PropertyChangedEventHandler);

case "Windows.UI.Xaml.Data.PropertyChangedEventArgs":
return typeof(PropertyChangedEventArgs);

case "Windows.UI.Xaml.Interop.TypeName":
return typeof(Type);

// TODO: is anything missing?
}

return null;
}

/// <summary>
Expand Down

0 comments on commit 60f24c3

Please sign in to comment.