Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -1104,6 +1104,59 @@ public static void ImplType(
ModuleDefinition module,
out TypeDefinition implType)
{
TypeSignature keyType = dictionaryType.TypeArguments[0];
TypeSignature valueType = dictionaryType.TypeArguments[1];

// Define the 'Lookup' method
MethodDefinition lookupMethod = InteropMethodDefinitionFactory.IReadOnlyDictionary2Impl.Lookup(
readOnlyDictionaryType: dictionaryType,
lookupMethod: interopReferences.IReadOnlyDictionaryAdapter2Lookup(keyType, valueType),
interopReferences: interopReferences,
emitState: emitState,
module: module);

// Define the 'get_Size' method
MethodDefinition sizeMethod = InteropMethodDefinitionFactory.IReadOnlyDictionary2Impl.get_Size(
readOnlyDictionaryType: dictionaryType,
sizeMethod: interopReferences.IDictionaryAdapter2Size(keyType, valueType),
interopReferences: interopReferences,
module: module);

// Define the 'HasKey' method
MethodDefinition hasKeyMethod = InteropMethodDefinitionFactory.IReadOnlyDictionary2Impl.HasKey(
readOnlyDictionaryType: dictionaryType,
containsKeyMethod: interopReferences.IDictionary2ContainsKey(keyType, valueType),
interopReferences: interopReferences,
emitState: emitState,
module: module);

// Define the 'GetView' method
MethodDefinition getViewMethod = InteropMethodDefinitionFactory.IDictionary2Impl.GetView(
dictionaryType: dictionaryType,
interopReferences: interopReferences,
emitState: emitState,
module: module);

// Define the 'Insert' method
MethodDefinition insertMethod = InteropMethodDefinitionFactory.IDictionary2Impl.Insert(
dictionaryType: dictionaryType,
interopReferences: interopReferences,
emitState: emitState,
module: module);

// Define the 'Remove' method
MethodDefinition removeMethod = InteropMethodDefinitionFactory.IDictionary2Impl.Remove(
dictionaryType: dictionaryType,
interopReferences: interopReferences,
emitState: emitState,
module: module);

// Define the 'Clear' method
MethodDefinition clearMethod = InteropMethodDefinitionFactory.IDictionary2Impl.Clear(
dictionaryType: dictionaryType,
interopReferences: interopReferences,
module: module);

Impl(
interfaceType: ComInterfaceType.InterfaceIsIInspectable,
ns: InteropUtf8NameFactory.TypeNamespace(dictionaryType),
Expand All @@ -1113,7 +1166,14 @@ public static void ImplType(
interopReferences: interopReferences,
module: module,
implType: out implType,
vtableMethods: []);
vtableMethods: [
lookupMethod,
sizeMethod,
hasKeyMethod,
getViewMethod,
insertMethod,
removeMethod,
clearMethod]);

// Track the type (it may be needed by COM interface entries for user-defined types)
emitState.TrackTypeDefinition(implType, dictionaryType, "Impl");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System;
using System.Runtime.InteropServices;
using AsmResolver.DotNet;
using AsmResolver.DotNet.Code.Cil;
Expand Down Expand Up @@ -602,9 +601,9 @@ public static void ImplType(
module: module);

// Define the 'HasKey' method
MethodDefinition hasKeymethod = InteropMethodDefinitionFactory.IReadOnlyDictionary2Impl.HasKey(
MethodDefinition hasKeyMethod = InteropMethodDefinitionFactory.IReadOnlyDictionary2Impl.HasKey(
readOnlyDictionaryType: readOnlyDictionaryType,
hasKeyMethod: interopReferences.IReadOnlyDictionary2ContainsKey(keyType, valueType),
containsKeyMethod: interopReferences.IReadOnlyDictionary2ContainsKey(keyType, valueType),
interopReferences: interopReferences,
emitState: emitState,
module: module);
Expand All @@ -628,7 +627,7 @@ public static void ImplType(
vtableMethods: [
getAtMethod,
sizeMethod,
hasKeymethod,
hasKeyMethod,
splitMethod]);

// Track the type (it may be needed by COM interface entries for user-defined types)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ private static void Impl(
}

// Enforce that we did initialize all vtable entries
//ArgumentOutOfRangeException.ThrowIfNotEqual(vtableOffset, vftblType.Fields.Count, nameof(vtableMethods)); // TODO
ArgumentOutOfRangeException.ThrowIfNotEqual(vtableOffset, vftblType.Fields.Count, nameof(vtableMethods));

// Don't forget the 'ret' at the end of the static constructor
_ = cctor.CilMethodBody.Instructions.Add(Ret);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,21 @@ private static void TryTrackWindowsRuntimeGenericInterfaceTypeInstance(
// This is for the same reason why we need the other special cases in this method: members are not analyzed.
discoveryState.TrackKeyValuePairType(interopReferences.KeyValuePair2.MakeGenericValueType([.. typeSignature.TypeArguments]));

// Whenever we find an 'IDictionary<TKey, TValue>' instantiation, we also need to track the corresponding
// 'IReadOnlyDictionary<TKey, TValue>' instantiation. This is because that interface is needed to marshal
// the return value of the 'IMap<K, V>.GetView' method ('IMapView<K, V>'). Same as 'IVector<T>.GetView' above.
discoveryState.TrackIReadOnlyDictionary2Type(interopReferences.IReadOnlyDictionary2.MakeGenericReferenceType([.. typeSignature.TypeArguments]));

// We also need to track the constructed 'ReadOnlyDictionary<TKey, TValue>' type, as that is used by
// 'IDictionaryAdapter<TKey, TValue>.GetView' in case the input 'IDictionary<TKey, Tvalue>' instance doesn't implement
// 'IReadOnlyDictionary<TKey, TValue>' directly. Analogous to tracking 'ReadOnlyCollection<T>' above.
TryTrackGenericTypeInstance(
typeSignature: interopReferences.ReadOnlyDictionary2.MakeGenericReferenceType([.. typeSignature.TypeArguments]),
args: args,
discoveryState: discoveryState,
interopReferences: interopReferences,
module: module);

// When we discover a constructed 'IDictionary<TKey, TValue>' instantiation, we'll be generating a native object type during
// the emit phase, which is used to marshal anonymous objects. This derives from 'WindowsRuntimeDictionary<TKey, TValue, ...>'.
// For the 'Keys' and 'Values' properties, that base type will return instances of the 'DictionaryKeyCollection<TKey, TValue>'
Expand Down
Loading
Loading