Skip to content

Conversation

@Sergio0694
Copy link
Member

This PR adds docs explaining in detail all codegen to handle generic collection interfaces in CsWinRT 3.0.

@Sergio0694 Sergio0694 added documentation Improvements or additions to documentation AOT labels May 15, 2025
Copy link
Member

@jevansaks jevansaks left a comment

Choose a reason for hiding this comment

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

Posting my comments but I got a little lost in this writeup so I think we need an in-person review of some of this if you want thoughtful feedback.


This type derives from `WindowsRuntimeObject`, which provides all the usual support for IDIC, generated COM interfaces, and more. If needed, these RCW types (one per generic interface) can also contain additional state necessary to properly map the Windows Runtime interface behavior to the managed one. This is the case for `IEnumerator<T>`, which is slightly different than `IIterator<T>`, for instance.

Next, an interface is needed for each "Methods" implementation, for each generic interface. For `IIterator<T>`, it looks like this:
Copy link
Member

Choose a reason for hiding this comment

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

I was mostly with you until this point. "An interface is needed" -- why? How does this connect to the scenarios above? I assume there's some general-purpose C#/WinRT machinery that is trying to reach out for this, but when/where?

}
```

This is conceptually similar to `IWindowsRuntimeComWrappersCallback` (which is used for delegates and sealed runtime class names), with the main difference being that it is specialized for unsealed types (and interfaces). In this case, implementations need to know the runtime class name of the native object, to determine whether they can marshal it via the fast path using a statically visible RCW type (see below), or whether they should fallback to the logic to marshal arbitrary opaque object that is used when no static type information is available (which involves going through the interop type lookup to get the marshalling info, etc.).
Copy link
Member

Choose a reason for hiding this comment

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

Pretend I don't know anything about the current C#/WinRT implementation in this regard. What do I need to know/care about to evaluate this proposal? :)

Co-authored-by: Jeremy Koritzinsky <jekoritz@microsoft.com>
@Sergio0694 Sergio0694 merged commit 172fd76 into fhl/cswinrt-3.0 Jul 14, 2025
2 of 9 checks passed
@Sergio0694 Sergio0694 deleted the user/sergiopedri/generic-collections-docs branch July 14, 2025 20:54
Sergio0694 added a commit that referenced this pull request Sep 3, 2025
* Emit 'IIterableMethods' types

* Emit 'NativeObject' type for 'IEnumerable<T>'

* Emit 'ComWrappersCallback' type

* Emit 'ComWrappersMarshallerAttribute' type

* Emit 'Marshaller' type

* Emit 'InterfaceImpl' type

* Emit proxy types for 'IEnumerable<T>'

* Add 'WindowsRuntimeReadOnlyList<T>'

* Add infrastructure types for 'IReadOnlyList<T>'

* Add infrastructure types for 'IList<T>'

* Add 'WindowsRuntimeList<T>', minor tweaks

* Update WindowsRuntimeEnumerator{T}.cs

* Use 'field' keyword

* Minor tweaks, remove 'unsafe'

* Add infrastructure types for 'IReadOnlyDictionary<K, V>'

* Add 'ReadOnlyDictionaryKeyCollection<,>'

* Add 'ReadOnlyDictionaryValueCollection<,>'

* Use new collection types

* Add infrastructure types for 'IDictionary<K, V>'

* Emit 'IReadOnlyList1Vftbl' type

* Emit 'IList1Vftbl' type

* Emit 'IReadOnlyDictionary2Vftbl' type

* Emit 'IDictionary2Vftbl' type

* Emit 'IReadOnlyList<T>' vtable types

* Emit 'IVectorViewMethods' types

* Add missing 'BeforeFieldInit'-s

* Emit 'IReadOnlyListMethods' types

* Add 'IReadOnlyListAdapter<T>'

* Rework RCW types for generic collections

* Rework RCW types for generic dictionaries

* Implement missing dictionary methods

* Update codegen for 'IEnumerator<T>'

* Update codegen for 'IEnumerable<T>'

* Refactor 'ComputeReadOnlySpanHash'

* Add new 'ModuleDefinition' extension, minor tweaks

* Fix corlib types in 'IsConstructedGenericTypeVisitor'

* Gather constructed base interfaces

* Add two missing imports

* Emit 'NativeObject' for 'IReadOnlyList<T>'

* Remove unnecessary 'MemberReference'-s

* Rename discovery state type

* Add 'InteropGeneratorEmitState'

* Use fast lookup for type definitions

* Track missing 'IEnumerator<T>' types

* Emit stub 'Impl' type for 'IReadOnlyList<T>'

* Emit more 'IReadOnlyList<T>' types

* Fix reference signature of 'ConvertToUnmanaged'

* Fix type names for 'EventSource<...>' types

* Fix 'PropertySignature' declarations

* Emit 'InterfaceImpl' for 'IReadOnlyList<T>'

* Emit 'IList<T>' vtable types

* Minor code refactoring

* Emit stub 'IList<T>' vector types

* Simplify generic RCW-s infrastructure

* Emit 'IListMethods' types for 'IList<T>'

* Emit 'NativeObject' type for 'IList<T>', minor tweaks

* Refactor 'IID' properties to remove dependency cycles

* Share 'NativeObject' generation logic

* Share 'ComWrappersCallback' generation logic

* Share 'ComWrappersMarshallerAttribute' generation logic

* Share 'Marshaller' generation logic

* Emit proxy type for 'IList<T>'

* Emit missing 'RemoveAt' method

* Add 'GetMethods' extension method

* Emit 'InterfaceImpl' type for 'IList<T>'

* Add and use 'AddMethodImplementation' extension

* Share 'Impl' generation logic

* Emit 'IID' and 'Vftbl' types for 'IReadOnlyDictionary<,>'

* Add 'SignatureComparer.MakeValueTupleComparer'

* Emit 'IID' and 'Vftbl' types for 'IDictionary<,>'

* Emit 'IMapViewMethods' types for 'IReadOnlyDictionary<,>'

* Emit 'IReadOnlyDictionaryMethods' types

* Emit more types for 'IReadOnlyDictionary<,>'

* Add 'MakeTypeSignatureExtensions'

* Update code to use new extensions

* Minor code tweaks to interop references

* Emit 'InterfaceImpl' for 'IReadOnlyDictionary<,>'

* Add and use 'PropertySignatureExtensions'

* Add and use 'WellKnownMethodAttributesFactory'

* Add 'CreateLdloc' extensions

* Add 'WellKnownCilMethodBodyFactory'

* Adopt new IDIC implementation factory

* Minor tweaks

* Emit remaining types for 'IReadOnlyDictionary<,>'

* Update 'IDictionaryMethods<TKey, TValue>'

* Emit 'IMapMethods' types

* Emit 'IDictionaryMethods' types

* Use '[StructLayout]' to suppress 'CS0649' warnings

* Fix codegen for 'IDictionary<,>.CopyTo'

* Emit more 'IDictionary<,>' types

* Emit 'InterfaceImpl' type for 'IDictionary<,>'

* Fix 'ldarg' opcodes in DIMs

* Emit 'ICollection<T>.IsReadOnly' DIMs

* Use parameterless 'CilMethodBody' constructor

* Use UTF8 literals in 'InteropReferences'

* Add 'MethodDefinitionExtensions'

* Refactor 'IDictionary2' builder logic

* Emit stub 'Impl' type for 'IDictionary<,>'

* Add empty 'WinRT.Interop.Tasks'

* Add draft of 'CsWinRTGenerator' task

* Switch 'cswinrtgen' to using a response file

* Add support to save repro file

* Update WinRT.Interop.Tasks.csproj

* Save original file paths to JSON file

* Add message when saving debug repro

* Fix 'WinRT.Interop.dll' module name

* Rework runtime class name lookup methods

* Update the task namespace

* Remove leftover attributes

* Update 'WindowsRuntimeTypeHierarchy' forward classes

* Fix a typo

* Remove codegen for 'ComputeReadOnlySpanHash'

* Implement 'TryGetBaseRuntimeClassName' in C#

* Implement 'TryGetNextBaseRuntimeClassName' in C#

* Fix codegen and calls for next parent lookups

* Update to .NET 10, remove polyfills

* Add bindings for 'IInspectableVftbl'

* Remove 'CWT<,>' closures

* Remove 'CreateValueCallback' uses

* Remove unnecessary 'HSTRING' casts

* Minor tweaks

* Rename Windows runtime type map group

* Add partial logic for 'ComWrappers', fix XML docs

* Add logic to emit type map attributes

* Emit type map attributes for existing types

* Fix assembly for type map attributes

* Implement 'CreateObject'

* Add 'WindowsRuntimeObjectMarshaller.TryUnwrap'

* Implement 'ReleaseObjects'

* Fix vtable pointer casts

* Unwrap CCW pointers when marshalling

* Remove unnecessary 'Unsafe.AsRef' calls

* Centralize 'WindowsRuntimeComWrappers' logic

* Cache derived marshalling info, minor refactoring

* Simplify 'ComWrappers', fix some derived cases

* Simplify two 'Unsafe' calls

* Tweak some 'WindowsRuntimeObjectReference' factories

* Add 'WindowsRuntimeMarshal'

* 'WindowsRuntimeMarshal' API tweaks

* Use 'CreateObjectReferenceUnsafe' internally

* Add and use 'GetOrCreateObjectForComInstanceUnsafe'

* Fix 'CreatedWrapperFlags' for 'Uri'

* Tweak 'WindowsRuntimeComWrappersMarshallerAttribute'

* Use 'WindowsRuntimeMarshal' in generator

* Remove unnecessary 'ComputeVtables' method

* Add and use 'CilOutParameterIndices' extension

* Minor code refactoring

* Rename some APIs

* Fix 'IReferenceVftbl.get_ValueUnsafe'

* Tweak 'CsWinRTGenerator'

* Add 'InteropGeneratorTest'

* Tweak target and make messages visible

* Fix formatting in response file

* Escape the path to response files

* Minor code refactoring

* Add option to validate assembly versions

* Add new property to MSBuild task, update target

* Fix some 'IReference<HString>' stubs

* Update 'WinRT.Interop.dll' metadata in target

* Tweak target to copy to output and clean

* Trim arguments in 'cswinrtgen'

* Add support for additional arguments

* Minor tweaks to 'WindowsRuntimeComWrappers'

* Add 'TreatWarningsAsErrors' option

* Use UTF8 overload

* Implement more 'IDIC' logic

* Implement 'GetObjectReferenceForInterface'

* Implement more 'WindowsRuntimeObject' methods

* Tweak 'DynamicInterfaceCastableImplementationForwarderAttribute'

* Generalize type signature visitor logic

* Add discovery logic for SZ array types

* Add 'WindowsRuntimeArrayMarshaller' APIs

* Add and use 'HRESULTExtensions' internally

* Use '[UnsafeAccessorType]' from BLC, remove polyfill

* Handle arrays of arrays in visitor

* Emit 'IReferenceArrayVftbl' type

* Emit stub array marshaller types

* Emit 'IWindowsRuntimeArrayComWrappersCallback' types

* Emit 'Impl' types for SZ array types

* Emit 'IReferenceArrayInterfaceEntries' type

* Emit 'ArrayComWrappersMarshallerAttribute' types

* Emit proxy types and type map for array types

* Fix name mangling for SZ array types

* Optimize 'InteropUtf8NameFactory'

* Update AsmResolver, fix runtime context

* Simplify member accesses

* Fix 'CreatedWrapperFlags' parameter

* Fix 'Invoke' signature for delegate types

* Escape backtick characters

* Add `WinRT.Interop.dll` public API spec (#2002)

* Create winrt-interop-dll-spec.md

* Fix formatting

* Add spec for name mangling for arrays

* Add notes on build infrastructure

* Add technical docs on generic interfaces codegen (#1989)

* Add 'generic-interfaces-infrastructure.md'

* Tweaks and mention stateless adapters

* Rename docs file

* Create marshalling-arrays.md

* Fix typo

* Fix another typo

* Fix typo

Co-authored-by: Jeremy Koritzinsky <jekoritz@microsoft.com>

---------

Co-authored-by: Jeremy Koritzinsky <jekoritz@microsoft.com>

* Replace backticks with apostrophes in mangled names

* Add error for referencing CsWinRT 2.x

* Add 'ValidateWinRTRuntimeDllVersion2References'

* Fix XML doc

* Add 'EnableIncrementalGeneration' parameter

* Add 'WindowsRuntimeObjectMarshaller.ConvertToManaged' overload

* Move 'WindowsRuntimeTypeHierarchy'

* Update 'cswinrtgen' dependencies

* Add 'WindowsRuntimeArrayHelpers'

* Tweak runtime class name for reference arrays

* Add validation methods to 'WindowsRuntimeArrayHelpers'

* Partially implement 'Free' for array types

* Fix two build warnings

* Add shared stub for 'Type'

* Add 'DerivedComposed' and 'Sealed' types

* Remove temporary test projects

* Add new projects to .sln file

* Update an incorrect comment

* Fix build errors in cswinrtgen

* Fix 'WindowsRuntimeObject' constructors (WIP)

* Fix 'InitializeFromManagedTypeUnsafe'

* Incremental 'WindowsRuntimeObject' changes

* Remove asmresolver-nightly source from nuget.config

Deleted the asmresolver-nightly package source from nuget.config to streamline package sources and possibly resolve conflicts or redundancy.

* Add exception for missing type hierarchy entries

Introduces a sanity check in WindowsRuntimeTypeHierarchyBuilder to throw a specific exception when no type hierarchy key-value pairs are discovered. Adds TypeHierarchyNoDiscoveredKeyValuePairs to WellKnownInteropExceptions for clearer error reporting in this scenario.

* Remove duplicate method declarations in IDL file

Eliminated repeated static method declarations for unboxing types in TestComponentCSharp.idl to improve clarity and maintainability.

* Add new projects to solution file

Added WinRT.Interop.Generator and WinRT.Runtime2 projects to cswinrt.slnx to include them in the solution.

* Suppress analyzer warnings in project files

Added NoWarn for AD0001 to both csproj files to work around exceptions from ILLink.RoslynAnalyzer.DynamicallyAccessedMembersAnalyzer. Also suppressed IDE0060 in WinRT.Interop.Generator for unimplemented methods.

* Rename IWindowsRuntimeComWrappersCallback references

Updated references from IWindowsRuntimeComWrappersCallback to IWindowsRuntimeObjectComWrappersCallback in InteropTypeDefinitionBuilder.Delegate.cs and InteropReferences.cs to reflect API changes and improve clarity.

* Update comments and method signature in delegate builder

Clarified comments regarding local variable declarations and updated the 'ComputeVtables' method comment to reflect its override status in InteropTypeDefinitionBuilder.Delegate.

* Clarify constructor definition in EventSource builder

Added comments to explain the constructor implementation for EventSource types, noting that initialization logic resides in the base 'EventSource<T>' type. This improves code readability and developer understanding.

* Refactor method body assignment for iterator methods

Replaces 'Instructions' with 'CilInstructions' when assigning method bodies for 'HasCurrent' and 'MoveNext' methods in InteropTypeDefinitionBuilder.IEnumerator1.cs. This change improves consistency and clarity in method body construction.

* Fix comment to correctly reference 'MoveNext' method

Updated a comment to refer to the 'MoveNext' method instead of 'Reset' in InteropTypeDefinitionBuilder.IEnumerator1.cs for clarity and accuracy.

* Tweak error message for CsWinRT 2.x

Co-authored-by: Manodasan Wignarajah <mawign@microsoft.com>

* Fix a typo

Co-authored-by: Manodasan Wignarajah <mawign@microsoft.com>

* Fix marshaller usage in event args wrappers

Replaces incorrect 'value' parameter with 'result' in calls to ConvertToManaged for NotifyCollectionChangedEventArgs and DataErrorsChangedEventArgs marshallers, ensuring correct object conversion.

* Fix IID selection for INotifyPropertyChanged

Corrects the interface ID assignment to use INotifyPropertyChanged instead of INotifyCollectionChanged based on the WindowsRuntimeFeatureSwitches setting.

* Fix incorrect value being marshalled

Co-authored-by: Manodasan Wignarajah <mawign@microsoft.com>

* Fix more incorrect marshalled values

* Fix a few typos

* Update IID to IPropertyValue in IPropertyValueImpl

Changed the IID property in IPropertyValueImpl to reference WellKnownInterfaceIds.IID_IPropertyValue instead of IID_IInspectable to ensure correct interface identification.

* Fix incorrect release of activation factory pointer

Changed the ReleaseUnsafe call to release activationFactoryUnknown instead of activationFactory, ensuring the correct COM pointer is released after QueryInterface.

* Fix parameter name in array marshaller call

Replaces 'value' with 'referencePtr' in the call to IReferenceArrayVftbl.get_ValueUnsafe to ensure the correct pointer is used for unboxing the underlying array.

* Add StructLayout to IUnknownVftbl struct

Applied [StructLayout(LayoutKind.Sequential)] to the IUnknownVftbl struct to ensure proper memory layout for interop scenarios. This change improves compatibility with native code expecting a sequential layout.

* Suppress CS0649 warning in IUnknownImpl.cs

Added #pragma warning disable CS0649 to prevent compiler warnings about unassigned fields in the IUnknownImpl.cs file.

* Remove unused System.Runtime.InteropServices imports

Cleaned up unnecessary using directives for System.Runtime.InteropServices in several files under InteropServices to improve code clarity and reduce clutter.

* Remove explicit type annotations from lambda parameters

Simplified lambda expressions in AddOrUpdate by removing explicit type annotations from parameters, relying on type inference for improved readability.

* Suppress additional compiler warnings in source files

Added #pragma warning disable directives for CS8618, IDE0059, and IDE0060 in WindowsRuntimeObject.cs and IDE0060 in RestrictedErrorInfo.cs to suppress specific compiler warnings. These are marked as TODO for future review.

* Suppress type map trim warnings

* Add IsWindowsRuntimeAssembly check to module filtering

Extended module filtering logic to include assemblies identified as Windows Runtime assemblies, not just those referencing Windows SDK projections. Introduced IsWindowsRuntimeAssembly property to WindowsRuntimeExtensions and updated relevant checks in IgnoreAccessChecksToBuilder and InteropGenerator.Discover.

* Swap parameterless and parameterized activation methods

Reordered and updated ActivateInstanceUnsafe overloads: the parameterless version now activates sealed Windows Runtime types with no constructor parameters, while the parameterized version supports an additional string parameter. XML documentation was updated to clarify usage and method signatures were adjusted accordingly.

* Improve interface marshalling for inspectable objects

Refactored WindowsRuntimeInterfaceMarshaller to handle anonymous inspectable objects by unwrapping native references when possible, avoiding unnecessary CCW creation. Enhanced exception handling for QueryInterface failures with more informative error messages.

* Correct DateTimeOffset ticks calculation in comments

Updated comments in SystemTypes.cs and DateTimeOffset.cs to use the correct second value (0 instead of 1) when calculating ticks for DateTimeOffset(1601, 1, 1, 0, 0, 0, TimeSpan.Zero). This ensures documentation matches the actual constant value.

* Fix typo in method name ConvertToManaged

Corrected the spelling of the method name from ConvertToMananaged to ConvertToManaged in INotifyDataErrorInfoMethods to ensure proper method invocation.

* Fix duplicated wording in XML documentation comments

Removed redundant phrasing ('The IID for') from XML doc comments in NotifyCollectionChangedEventHandlerReferenceImpl and PropertyChangedEventHandlerReferenceImpl to improve clarity.

* Release IReference pointer before asserting HRESULT

Updated marshalling logic to always release the temporary IReference<T> interface pointer before asserting the HRESULT from get_ValueUnsafe. This ensures proper resource cleanup even if get_Value fails.

* Remove unnecessary blank lines in ABI event handlers

Cleaned up formatting by removing extraneous blank lines before event handler methods in INotifyCollectionChanged, INotifyDataErrorInfo, and INotifyPropertyChanged implementations.

---------

Co-authored-by: Jeremy Koritzinsky <jekoritz@microsoft.com>
Co-authored-by: Manodasan Wignarajah <mawign@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AOT documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants