Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 21 additions & 37 deletions src/WinRT.Runtime/ComWrappersSupport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ internal static (InspectableInfo inspectableInfo, List<ComInterfaceEntry> interf
}

if (type.FullName.StartsWith("ABI.", StringComparison.Ordinal))
{
{
type = Projections.FindCustomPublicTypeForAbiType(type) ?? type.Assembly.GetType(type.FullName.Substring("ABI.".Length)) ?? type;
}

Expand All @@ -280,59 +280,44 @@ private static bool IsAbiNullableDelegate(Type implementationType)
}

private static bool IsIReferenceArray(Type implementationType)
{
return implementationType.FullName.StartsWith("Windows.Foundation.IReferenceArray`1", StringComparison.Ordinal);
{
return implementationType.IsGenericType && implementationType.GetGenericTypeDefinition() == typeof(Windows.Foundation.IReferenceArray<>);
}

private static Func<IInspectable, object> CreateKeyValuePairFactory(Type type)
{
var parms = new[] { Expression.Parameter(typeof(IInspectable), "obj") };
return Expression.Lambda<Func<IInspectable, object>>(
Expression.Call(type.GetHelperType().GetMethod("CreateRcw", BindingFlags.Public | BindingFlags.Static),
parms), parms).Compile();
var createRcwFunc = (Func<IInspectable, object>) type.GetHelperType().GetMethod("CreateRcw", BindingFlags.Public | BindingFlags.Static).
CreateDelegate(typeof(Func<IInspectable, object>));
return createRcwFunc;
}

internal static Func<IntPtr, object> CreateDelegateFactory(Type type)
{
return DelegateFactoryCache.GetOrAdd(type, (type) =>
{
var parms = new[] { Expression.Parameter(typeof(IntPtr), "ptr") };
return Expression.Lambda<Func<IntPtr, object>>(
Expression.Call(type.GetHelperType().GetMethod("CreateRcw", BindingFlags.Public | BindingFlags.Static),
parms), parms).Compile();
var createRcwFunc = (Func<IntPtr, object>)type.GetHelperType().GetMethod("CreateRcw", BindingFlags.Public | BindingFlags.Static).
CreateDelegate(typeof(Func<IntPtr, object>));
return createRcwFunc;
});
}

private static Func<IInspectable, object> CreateNullableTFactory(Type implementationType)
{
Type helperType = implementationType.GetHelperType();

ParameterExpression[] parms = new[] { Expression.Parameter(typeof(IInspectable), "inspectable") };
return Expression.Lambda<Func<IInspectable, object>>(
Expression.Convert(Expression.Call(helperType.GetMethod("GetValue", BindingFlags.Static | BindingFlags.NonPublic),
parms), typeof(object)), parms).Compile();
{
var getValueMethod = implementationType.GetHelperType().GetMethod("GetValue", BindingFlags.Static | BindingFlags.NonPublic);
return (IInspectable obj) => getValueMethod.Invoke(null, new[] { obj });
}

private static Func<IInspectable, object> CreateAbiNullableTFactory(Type implementationType)
{
ParameterExpression[] parms = new[] { Expression.Parameter(typeof(IInspectable), "inspectable") };
return Expression.Lambda<Func<IInspectable, object>>(
Expression.Convert(Expression.Call(implementationType.GetMethod("GetValue", BindingFlags.Static | BindingFlags.NonPublic),
parms), typeof(object)), parms).Compile();
{
var getValueMethod = implementationType.GetMethod("GetValue", BindingFlags.Static | BindingFlags.NonPublic);
return (IInspectable obj) => getValueMethod.Invoke(null, new[] { obj });
}

private static Func<IInspectable, object> CreateArrayFactory(Type implementationType)
{
Type helperType = implementationType.GetHelperType();
Type vftblType = helperType.FindVftblType();

ParameterExpression[] parms = new[] { Expression.Parameter(typeof(IInspectable), "inspectable") };
var createInterfaceInstanceExpression = Expression.New(helperType.GetConstructor(new[] { typeof(ObjectReference<>).MakeGenericType(vftblType) }),
Expression.Call(parms[0],
typeof(IInspectable).GetMethod(nameof(IInspectable.As)).MakeGenericMethod(vftblType)));

return Expression.Lambda<Func<IInspectable, object>>(
Expression.Property(createInterfaceInstanceExpression, "Value"), parms).Compile();
{
var getValueFunc = (Func<IInspectable, object>)implementationType.GetHelperType().GetMethod("GetValue", BindingFlags.Static | BindingFlags.NonPublic).
CreateDelegate(typeof(Func<IInspectable, object>));
return getValueFunc;
}

// This is used to hold the reference to the native value type object (IReference) until the actual value in it (boxed as an object) gets cleaned up by GC
Expand All @@ -357,9 +342,8 @@ private static Func<IInspectable, object> CreateCustomTypeMappingFactory(Type cu
throw new MissingMethodException();
}

var parms = new[] { Expression.Parameter(typeof(IInspectable), "obj") };
return Expression.Lambda<Func<IInspectable, object>>(
Expression.Call(fromAbiMethod, Expression.Property(parms[0], "ThisPtr")), parms).Compile();
var fromAbiMethodFunc = (Func<IntPtr, object>) fromAbiMethod.CreateDelegate(typeof(Func<IntPtr, object>));
return (IInspectable obj) => fromAbiMethodFunc(obj.ThisPtr);
}

internal static Func<IInspectable, object> CreateTypedRcwFactory(Type implementationType, string runtimeClassName = null)
Expand Down
58 changes: 24 additions & 34 deletions src/WinRT.Runtime/ComWrappersSupport.net5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,56 +221,46 @@ public static void InitializeComWrappers(ComWrappers wrappers = null)

private static Func<IInspectable, object> CreateFactoryForImplementationType(string runtimeClassName, Type implementationType)
{
ParameterExpression[] parms = new[] { Expression.Parameter(typeof(IInspectable), "inspectable") };

if (implementationType.IsGenericType)
{
var genericType = implementationType.GetGenericTypeDefinition();

Type genericImplType = null;
if (genericType == typeof(IList<>))
{
return Expression.Lambda<Func<IInspectable, object>>(
Expression.New(typeof(IListImpl<>).MakeGenericType(new[] { implementationType.GetGenericArguments()[0] }).GetConstructor(BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance, null, new[] { typeof(IObjectReference) }, null),
Expression.Property(parms[0], nameof(WinRT.IInspectable.ObjRef))),
parms).Compile();
genericImplType = typeof(IListImpl<>);
}
if (genericType == typeof(IDictionary<,>))
else if (genericType == typeof(IDictionary<,>))
{
return Expression.Lambda<Func<IInspectable, object>>(
Expression.New(typeof(IDictionaryImpl<,>).MakeGenericType(new[] { implementationType.GetGenericArguments()[0], implementationType.GetGenericArguments()[1] }).GetConstructor(BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance, null, new[] { typeof(IObjectReference) }, null),
Expression.Property(parms[0], nameof(WinRT.IInspectable.ObjRef))),
parms).Compile();
genericImplType = typeof(IDictionaryImpl<,>);
}
if (genericType == typeof(IReadOnlyDictionary<,>))
else if (genericType == typeof(IReadOnlyDictionary<,>))
{
return Expression.Lambda<Func<IInspectable, object>>(
Expression.New(typeof(IReadOnlyDictionaryImpl<,>).MakeGenericType(new[] { implementationType.GetGenericArguments()[0], implementationType.GetGenericArguments()[1] }).GetConstructor(BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance, null, new[] { typeof(IObjectReference) }, null),
Expression.Property(parms[0], nameof(WinRT.IInspectable.ObjRef))),
parms).Compile();
genericImplType = typeof(IReadOnlyDictionaryImpl<,>);
}
if (genericType == typeof(IReadOnlyList<>))
else if (genericType == typeof(IReadOnlyList<>))
{
return Expression.Lambda<Func<IInspectable, object>>(
Expression.New(typeof(IReadOnlyListImpl<>).MakeGenericType(new[] { implementationType.GetGenericArguments()[0] }).GetConstructor(BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance, null, new[] { typeof(IObjectReference) }, null),
Expression.Property(parms[0], nameof(WinRT.IInspectable.ObjRef))),
parms).Compile();
}
if (genericType == typeof(IEnumerable<>))
genericImplType = typeof(IReadOnlyListImpl<>);
}
else if (genericType == typeof(IEnumerable<>))
{
return Expression.Lambda<Func<IInspectable, object>>(
Expression.New(typeof(IEnumerableImpl<>).MakeGenericType(new[] { implementationType.GetGenericArguments()[0] }).GetConstructor(BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance, null, new[] { typeof(IObjectReference) }, null),
Expression.Property(parms[0], nameof(WinRT.IInspectable.ObjRef))),
parms).Compile();
}
genericImplType = typeof(IEnumerableImpl<>);
}

if (genericImplType != null)
{
var createRcw = genericImplType.MakeGenericType(implementationType.GetGenericArguments()).GetMethod("CreateRcw", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(IInspectable) }, null);
return (Func<IInspectable, object>)createRcw.CreateDelegate(typeof(Func<IInspectable, object>));
}
}

if (implementationType.IsInterface)
{
return obj => obj;
}

return Expression.Lambda<Func<IInspectable, object>>(
Expression.New(implementationType.GetConstructor(BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance, null, new[] { typeof(IObjectReference) }, null),
Expression.Property(parms[0], nameof(WinRT.IInspectable.ObjRef))),
parms).Compile();
}

var constructor = implementationType.GetConstructor(BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance, null, new[] { typeof(IObjectReference) }, null);
return (IInspectable obj) => constructor.Invoke(new[] { obj.ObjRef });
}
}

Expand Down
43 changes: 22 additions & 21 deletions src/WinRT.Runtime/GuidGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,17 @@ public static Guid GetIID(Type type)
}

public static string GetSignature(Type type)
{
{
if (type == typeof(object))
{
return "cinterface(IInspectable)";
}

if (type == typeof(string))
{
return "string";
}

var helperType = type.FindHelperType();
if (helperType != null)
{
Expand All @@ -43,18 +53,6 @@ public static string GetSignature(Type type)
}
}

type = type.IsInterface ? (type.GetAuthoringMetadataType() ?? type) : type;
if (type == typeof(object))
{
return "cinterface(IInspectable)";
}

if (type.IsGenericType)
{
var args = type.GetGenericArguments().Select(t => GetSignature(t));
return "pinterface({" + GetGUID(type) + "};" + String.Join(";", args) + ")";
}

if (type.IsValueType)
{
switch (type.Name)
Expand Down Expand Up @@ -88,20 +86,23 @@ public static string GetSignature(Type type)
}
}
}

type = type.IsInterface ? (type.GetAuthoringMetadataType() ?? type) : type;

if (type == typeof(string))
if (type.IsGenericType)
{
return "string";
}

if (Projections.TryGetDefaultInterfaceTypeForRuntimeClassType(type, out Type iface))
var args = type.GetGenericArguments().Select(t => GetSignature(t));
return "pinterface({" + GetGUID(type) + "};" + String.Join(";", args) + ")";
}

if (type.IsDelegate())
{
return "rc(" + type.FullName + ";" + GetSignature(iface) + ")";
return "delegate({" + GetGUID(type) + "})";
}

if (type.IsDelegate())
if (type.IsClass && Projections.TryGetDefaultInterfaceTypeForRuntimeClassType(type, out Type iface))
{
return "delegate({" + GetGUID(type) + "})";
return "rc(" + type.FullName + ";" + GetSignature(iface) + ")";
}

return "{" + type.GUID.ToString() + "}";
Expand Down
2 changes: 1 addition & 1 deletion src/WinRT.Runtime/Interop/IUnknownVftbl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ unsafe struct IUnknownVftbl
public static IUnknownVftbl AbiToProjectionVftbl => ComWrappersSupport.IUnknownVftbl;
public static IntPtr AbiToProjectionVftblPtr => ComWrappersSupport.IUnknownVftblPtr;

internal static readonly Guid IID = new(0, 0, 0, 0xC0, 0, 0, 0, 0, 0, 0, 0x46);
internal static readonly Guid IID = InterfaceIIDs.IUnknown_IID;

// Avoids boxing when using default Equals.
internal bool Equals(IUnknownVftbl other)
Expand Down
2 changes: 1 addition & 1 deletion src/WinRT.Runtime/Interop/IWeakReferenceSource.net5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ static class IWeakReferenceSourceMethods
[Guid("00000038-0000-0000-C000-000000000046")]
internal unsafe interface IWeakReferenceSource : global::WinRT.Interop.IWeakReferenceSource
{
internal static readonly Guid IID = new(0x00000038, 0, 0, 0xC0, 0, 0, 0, 0, 0, 0, 0x46);
internal static readonly Guid IID = InterfaceIIDs.IWeakReferenceSource_IID;

public static IntPtr AbiToProjectionVftablePtr;
static unsafe IWeakReferenceSource()
Expand Down
Loading