C#/WinRT Language Projection
repository·master·Indexed 20 days ago
https://github.com/microsoft/cswinrtA language projection that allows C# developers to consume Windows Runtime (WinRT) APIs using natural .NET idioms. It decouples WinRT support from the .NET runtime and compiler, enabling support for modern .NET (5+) and WinUI 3. The project provides the Microsoft.Windows.CsWinRT NuGet package for generating projection sources from .winmd files and includes tools for customizing build behavior via MSBuild properties, optimizing binary size, and comparing benchmark results.
What's inside C#/WinRT
- Microsoft.Windows.CsWinRT is a projection tool that provides packaged WinRT (Windows Runtime) support for the C# language. It allows C# developers to consume WinRT APIs without requiring the C# compiler to have built-in knowledge of WinRT. It is compatible with .NET Standard 2.0 and later versions.
Overview of the C#/WinRT Projection Sample
masterThis sample demonstrates the end-to-end workflow for bridging C++/WinRT components with .NET applications. Specifically, it shows how to:
- Use the C#/WinRT package to generate a C# .NET projection interop assembly from an existing C++/WinRT component.
- Distribute the component and its interop assembly together as a single NuGet package.
- Consume that component within a .NET 6 C# console application.
Understand the C#/WinRT Authoring Demo sample
masterThe AuthoringDemo sample demonstrates the end-to-end workflow of creating a WinRT component in C# and consuming it in other languages.
Component Authoring
AuthoringDemo is a C# .NET 6 class library that uses the C#/WinRT NuGet package to generate a WinRT component. It contains two runtime classes,
Example.csandFolderEnumeration.cs, which showcase how to use basic types and WinRT types within a component.Consumption Scenarios
The sample provides two different ways to consume the
AuthoringDemocomponent via project references:- C++/WinRT Console App: The
CppConsoleAppproject is a Windows Console Application that consumes the component. - WinUI 3 C++ App: The
WinUI3CppAppproject is a desktop application using the Windows App SDK Blank App, Packaged (WinUI 3 in Desktop) template.
- C++/WinRT Console App: The
Understand the C#/WinRT Embedded Sample structure
masterThe sample demonstrates two primary ways to use C#/WinRT embedded support:
1. Consuming an embedded projection library
In this pattern, a library project (like
TestEmbeddedLibrary) embeds theWinRT.Runtimeand Windows SDK sources into its own output. Consumer apps then simply reference this library.- Example Apps:
Net8App,NetCore3App. - Key Benefit: The library targets multiple frameworks (e.g.,
net8.0-windows,netstandard2.0,net48) while providing access to the latest Windows SDK APIs.
2. Generating an embedded projection within the app
In this pattern, the application itself generates and embeds the projection by referencing C++/WinRT components directly via package references.
- Example Apps:
Net8App.Bootstrap,NetFrameworkApp. - Mechanism: The app references C++/WinRT components (like Alpha, Beta, or Gamma) and creates the projection locally within the app project.
- Example Apps:
What is the C#/WinRT Language Projection?
masterC#/WinRT is an adapter (projection) that enables C# developers to use Windows Runtime (WinRT) APIs in a natural and familiar way. It hides the complexities of interop between C# and WinRT interfaces and maps WinRT types to appropriate .NET equivalents, such as:
- Strings
- URIs
- Common value types
- Generic collections
Unlike older versions of .NET, C#/WinRT does not require built-in WinRT knowledge in the C# compiler or the .NET Runtime. Instead, it uses tooling to generate C# code from
*.winmdfiles for consumption, or generates*.winmdfiles for authoring scenarios.Understand Managed Component Hosting with WinRT.Host.dll
masterManaged C#/WinRT runtime components are hosted using
WinRT.Host.dll, a native DLL that acts as an activation adapter. It uses theHostFxrlibrary to host the CLR and provides a bridge between native client code and the managed target assembly that implements the runtime class.Key Terminology
- Client: The caller of
RoGetActivationFactory. - Target: The managed assembly implementing the runtime class.
- Class: The activatable runtime class.
- Host: The activation adapter (e.g.,
WinRT.Host.dll) that hosts the managed implementation.
- Client: The caller of
Understand the C#/WinRT Architecture
masterAll C#/WinRT assemblies depend on the C#/WinRT runtime assembly,
WinRT.Runtime.dll. This runtime assembly provides an abstraction layer over the .NET runtime (supporting .NET 5+) and implements core features for all projected WinRT types, including:- WinRT activation
- Marshaling logic
- COM wrapper lifetime management
Understand the C#/WinRT runtime assembly (WinRT.Runtime.dll)
masterThe
WinRT.Runtime.dllassembly provides an abstraction layer over the .NET 5 runtime. It is essential for WinUI 3 applications to manage memory correctly via Xaml reference tracking support.For all projected C#/WinRT types, the runtime assembly implements:
- WinRT activation and marshaling logic
- Custom type mappings (primarily for WinUI)
- COM Wrapper management
IDynamicInterfaceCastableandComImportcasting support- Extension methods common to projected types
Be aware of default value differences in projected WinRT types
masterSome WinRT types may have different default values when projected into C#. For example,Windows.Foundation.DateTimeis projected toSystem.DateTimeOffset, which has a different default value. Avoid relying on default values for these types.Understand the constraints of private projections
masterWhen using private projections, keep the following architectural constraints in mind:
- Type Accessibility: Projected types are not accessible outside the module that generated them.
- Type Disjointness: You can mix global and private projections, but you must ensure the sets of types are disjoint. If a type is included in both a global and a private projection, you will generate duplicate types.
- Ambiguity Issues: An application cannot reference two different libraries if both libraries contain the same private projection. This causes ambiguity because types with the same name exist in different assemblies.
Handle AOT and Trim-safety warnings in CsWinRT
masterWhen working with Ahead-of-Time (AOT) compilation or trimming, be aware of the following constraints enforced by the CsWinRT analyzer:
- Collection Expressions: Only use collection expressions when they are statically verifiable for AOT support (
CsWinRT1032). - ComImport Casts: Do not cast to
[ComImport]interface types when using WinRT objects in AOT scenarios (CsWinRT1033). - Runtime Class Casts: Avoid casting to WinRT runtime classes as they are not trim-safe (
CsWinRT1034). - IReference<T> Unboxing: Avoid casting to unboxed
IReference<T>values as they are not trim-safe (CsWinRT1035).
- Collection Expressions: Only use collection expressions when they are statically verifiable for AOT support (
Cast projected interfaces using C#-style casts
masterWith the introduction ofIDynamicInterfaceCastablesupport, projected interfaces can now be cast using standard C# syntax. However, if you are working with unprojected interfaces, you must continue to use the.As<T>()extension method.