Skip to content

System.Type Marshaling #2129

Open
kythant wants to merge 185 commits intostaging/3.0from
user/kythant/TypeHandling
Open

System.Type Marshaling #2129
kythant wants to merge 185 commits intostaging/3.0from
user/kythant/TypeHandling

Conversation

@kythant
Copy link

@kythant kythant commented Nov 25, 2025

No description provided.

@kythant kythant closed this Nov 25, 2025
@kythant kythant reopened this Nov 26, 2025
@kythant kythant closed this Nov 27, 2025
@kythant kythant reopened this Dec 1, 2025
kythant and others added 17 commits December 1, 2025 15:59
Simplifies and clarifies the handling of TypeReference creation, including improved comments and restructuring for primitive and proxy types. Ensures more consistent reporting of TypeKind and streamlines marshalling info usage.
Changed the TypeReference.Name field from string? to ReadOnlySpan<char> for improved memory safety and performance. Updated marshalling logic and related references to accommodate the new type.
Added [WindowsRuntimeMetadata] attributes to ABI type classes in WinRT.Runtime2 to specify their associated Windows contracts. This improves metadata clarity and contract mapping for types such as Boolean, Byte, Char, DateTimeOffset, Double, EventHandler, Exception, Guid, Int16, Int32, Int64, Numerics types, Object, Single, String, TimeSpan, Type, UInt16, UInt32, UInt64, and Uri.
Introduces TypeMapAssociation attributes for DynamicInterfaceCastableImplementationTypeMapGroup to INotifyDataErrorInfo, IDisposable, and IServiceProvider ABI interfaces. Also adds WindowsRuntimeMetadata and WindowsRuntimeClassName attributes to their respective interface implementations for improved WinRT interop.
Added logic to TypeMarshaller to support round-tripping C# primitive types (e.g., System.SByte) that are not Windows Runtime types. This ensures such types can be resolved even if not found in the WindowsRuntimeMarshallingInfo lookup.
kythant and others added 8 commits February 3, 2026 11:53
Remove the [WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] attribute from ABI.System.EventHandler and add a clarifying comment. This prevents automatic Windows Runtime mapping for EventHandler so that marshalling typeof(EventHandler) remains a custom type and aligns with existing special-case marshalling behavior.
Remove the WindowsRuntimeMappedMetadata and WindowsRuntimeClassName attributes from the DynamicInterfaceCastable implementation of global::System.IDisposable (IDisposableInterfaceImpl in ABI/System/IDisposable.cs). This change strips unnecessary WinRT annotations from the interface implementation; no other code modifications were made.
}

void write_struct_winrt_classname_attribute(writer& w, TypeDef const& type)
void write_winrt_classname_attribute(writer& w, TypeDef const& type)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
void write_winrt_classname_attribute(writer& w, TypeDef const& type)
void write_value_type_winrt_classname_attribute(writer& w, TypeDef const& type)

@Sergio0694 Sergio0694 force-pushed the user/kythant/TypeHandling branch from 550bc58 to 5b9ef4e Compare February 4, 2026 04:01
manodasanW and others added 19 commits February 4, 2026 00:12
* Add ICommand custom-mapped type support

Add support for System.Windows.Input.ICommand as a custom-mapped WinRT type. Creates a new InterfaceImpl type and explicit interface implementations (CanExecute, Execute and CanExecuteChanged add/remove) in a new builder file; registers type map attributes for ICommand; adds ICommand member references to InteropReferences; adds GetMethodsType helper and corresponding WellKnownInteropException when the associated Methods type cannot be resolved. Also adjusts TypeMapAttributes usage for metadata/runtime names and includes minor comments.

* Add INotifyPropertyChanged mapping and builders

Introduce support for System.ComponentModel.INotifyPropertyChanged: add a new partial builder (DynamicCustomMappedTypeMapEntriesBuilder.INotifyPropertyChanged.cs) that emits an InterfaceImpl type with add/remove accessors and the PropertyChanged event, and register a TypeMap via a new INotifyPropertyChangedInterfaceType helper in DynamicCustomMappedTypeMapEntriesBuilder.cs. Also add MemberReference entries for the add/remove PropertyChanged accessors to InteropReferences. Additionally, fix a local variable name in the ICommand builder file (canExecuteChangedProperty) to improve clarity.

* Rename INotifyPropertyChanged members in builder

Fix variable and method names in DynamicCustomMappedTypeMapEntriesBuilder to correctly reference System.ComponentModel.INotifyPropertyChanged.PropertyChanged. Renamed the add/remove method variables from the incorrect ICommandCanExecuteChanged names to add_INotifyPropertyChangedPropertyChangedMethod and remove_INotifyPropertyChangedPropertyChangedMethod, and renamed the event variable to propertyChangedProperty. No functional changes; this improves clarity and correctness of the implementation.

* Add INotifyCollectionChanged mapping and impl

Introduce support for System.Collections.Specialized.INotifyCollectionChanged by:

- Adding a new builder (DynamicCustomMappedTypeMapEntriesBuilder.INotifyCollectionChanged.cs) that emits an InterfaceImpl type with explicit add/remove accessors and an event using DynamicInterfaceCastableImplementation.
- Registering the INotifyCollectionChanged type in DynamicCustomMappedTypeMapEntriesBuilder (creates proxy/type-map attributes and wires the InterfaceImpl).
- Adding MemberReference properties for the CollectionChanged add/remove accessors to InteropReferences.

This enables generation of the proxy/interface mapping and dynamic interface castable implementation for collection-changed event handling.

* Remove DynamicInterfaceCastable implementations

Delete IDynamicInterfaceCastable implementations and associated TypeMapAssociation attributes from ABI files for INotifyCollectionChanged, INotifyPropertyChanged, and ICommand. The changes remove the generated dynamic interface wrapper types and leave only the static ABI helper implementations in these files, simplifying the ABI surface.

* Import called method references into module

Ensure method references are imported into the target module before emitting Call instructions. Replace direct references to forwardedMethod, forwardedMethod1, forwardedMethod2, and eventMethod with their imported equivalents (e.g. forwardedMethod.Import(module)) in WellKnownCilMethodBodyFactory to avoid cross-module reference issues when generating IL.

* Fix member references to INotify interfaces

Update InteropReferences.cs to use the correct interfaces when creating MemberReference instances for event add/remove methods. The properties for add/remove CollectionChanged and add/remove PropertyChanged previously referenced ICommand; they now reference INotifyCollectionChanged and INotifyPropertyChanged respectively so the member refs point to the proper interfaces.

* Cache MemberReference lookups in InteropReferences

Use a backing field (field ??= ...) to cache MemberReference instances for event adder/remover properties (ICommand.add/remove_CanExecuteChanged, INotifyCollectionChanged.add/remove_CollectionChanged, INotifyPropertyChanged.add/remove_PropertyChanged). This avoids recreating the MemberReference on each access; method signatures are unchanged.

* Rename local variable to methodsTypeReference

Rename the local TypeReference variable from comWrappersMarshallerTypeReference to methodsTypeReference to better reflect that it references the generated "{Type}Methods" type. Update its use in the Resolve check; behavior remains the same (throws if the methods type can't be resolved). This improves clarity of the code.

* Remove stray 'interop.' from XML docs

Remove accidental 'interop.' tokens from XML doc <summary> comments in DynamicCustomMappedTypeMapEntriesBuilder.cs. Cleans up the summaries for the methods that retrieve the marshaller attribute and the "Methods" type for a custom-mapped type; no behavioral changes.
Remove redundant global:: and System qualifiers from XML doc comments and event handler signatures, and replace fully-qualified ABI namespace usages with shorter identifiers where appropriate. This cleans up verbosity and improves readability/consistency across interop and ABI files (NotifyCollectionChangedEventHandler, PropertyChangedEventHandler, IObservableMap/Vector method impls, WindowsRuntimeObjectReferenceValue, TypeKind, and WindowsRuntimeObject).
Add assembly TypeMap entries to map the WinRT type "Windows.Foundation.PropertyType" to the local PropertyType type for both metadata and COM wrappers (including a trimTarget). Also annotate Windows.Foundation.PropertyType with WindowsRuntimeReferenceType(typeof(PropertyType?)) to mark it as a WinRT reference/nullable projection, improving interop and trimming behavior.
Expose Windows.Foundation.PropertyType in InteropReferences and update WindowsRuntimeExtensions to treat PropertyType as a recognized special/primitive Windows Runtime type. This ensures PropertyType can be resolved and matched by SignatureComparer in type checks alongside other foundation types (Point, Rect, Size, etc.).
Introduce WindowsRuntimeMarshallingInfo.GetOpaqueInfo(object) to centralize logic for selecting marshalling info for opaque/anonymous managed objects (special-casing Exception and Type, otherwise falling back to object). Update WindowsRuntimeComWrappers to call the new helper and remove the duplicate private GetAnonymousInspectableMarshallingInfo implementation. This refactors and consolidates marshalling selection into the TypeMapInfo class and uses AggressiveInlining for the new helper.
Retrieve WindowsRuntimeMarshallingInfo via TryGetInfo and fall back to GetOpaqueInfo when an exact match isn't available (e.g., types marshalled as object or RuntimeType). Reuse the resolved marshallingInfo to obtain vtable info and runtime class name instead of repeatedly calling GetInfo(instance.GetType()). This makes IInspectable implementations more robust for edge cases like Exception or marshalled-as-object instances.
* Add marshaller and IIDs for NotifyCollectionChangedAction

Introduce marshaling support for NotifyCollectionChangedAction and add corresponding interface IIDs.\n\n- Add NotifyCollectionChangedActionMarshaller and ComWrappers marshaller (new ABI file) to box/unbox the enum as a WinRT value type and provide vtable entries.\n- Update NotifyCollectionChangedEventArgs marshaller to reference the renamed IID_NotifyCollectionChangedEventArgs.\n- Add new GUID constants for IReferenceOfNotifyCollectionChangedAction to WellKnownWindowsInterfaceIIDs (generated) and update related IID names for NotifyCollectionChangedEventArgs.\n- Update template sources (.tt) and generated WellKnownXamlInterfaceIIDs to expose IID_NotifyCollectionChangedEventArgs and IID_IReferenceOfNotifyCollectionChangedAction.\n\nThese changes enable proper projection and COM interop for NotifyCollectionChangedAction values and their IReference wrappers in XAML/WinRT projections.

* Set runtime & metadata names for proxy type

Previously the proxy type used a null runtimeClassName (and later a null metadataTypeName) because the metadata type name wasn't fixed. Change updates the proxy/type-map calls to supply both runtime and metadata names via RuntimeClassNameGenerator.GetRuntimeClassName and MetadataTypeNameGenerator.GetMetadataTypeName, and updates the comment to note the proxy can be instantiated/boxed so both names are required.

* Map and mark AsyncStatus for WinRT reference

Add an assembly TypeMap mapping the WinRT metadata type "Windows.Foundation.AsyncStatus" to the managed AsyncStatus (with trimTarget set) to enable correct metadata-based type resolution and trimming. Also add a WindowsRuntimeReferenceType attribute to AsyncStatus (typeof(AsyncStatus?)) so it can be treated as an IReference<T> nullable reference for proper WinRT marshalling.

* Add WindowsRuntimeReferenceType support

Introduce support for WindowsRuntimeReferenceType by adding a referenceType parameter to InteropTypeDefinitionBuilder and emitting a WindowsRuntimeReferenceTypeAttribute when a reference type is provided (used to retrieve boxed types like Nullable<T>). Wire the new parameter through multiple builder call sites (passing null where not applicable). Add InteropReferences entries for WindowsRuntimeReferenceTypeAttribute and its constructor, and add a TypeReference for NotifyCollectionChangedAction.

* Add ValueType builder and notify collection action

Introduce a ValueType helper in DynamicCustomMappedTypeMapEntriesBuilder to create proxy types and TypeMapAttribute entries for custom-mapped value types (including boxed Nullable<T> reference types and marshaller attributes). Register NotifyCollectionChangedAction by calling ValueType with the appropriate trimTarget. Also update WindowsRuntimeExtensions to treat NotifyCollectionChangedAction as a known runtime type.

* Fix namespace for NotifyCollectionChangedAction

Update namespace from ABI.Windows.Foundation to ABI.System.Collections.Specialized to match the file path and the NotifyCollectionChangedAction marshaller, aligning the type with its intended namespace.
Change trim target for NotifyCollectionChangedAction from ToReferenceTypeSignature() to ToValueTypeSignature() in DynamicCustomMappedTypeMapEntriesBuilder.cs. This ensures the enum is treated as a value type during interop code generation and fixes trimming/marshalling behavior.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants