二十五、CSharp 与 WinRT 组件互操作
CLR #WinRT
C# 与 WinRT 组件互操作
在 Windows 平台开发中,WinRT(Windows Runtime)是一种现代组件模型,它统一了 C++、C#、VB.NET、JavaScript 等语言的互操作方式。而作为 .NET 开发者,我们需要知道如何 优雅地与 WinRT API 和组件交互。

1. CLR 投影与 WinRT 类型系统规则
CLR Projection 就像一层“语言翻译”,让 WinRT API 在 C# 世界中表现得更自然。
- 投影规则:
- WinRT 的
IVector<T>→ .NET 的IList<T> - WinRT 的
IMap<K,V>→ .NET 的IDictionary<K,V> - WinRT 的
IAsyncAction→ .NET 的Task - WinRT 的
IAsyncOperation<T>→ .NET 的Task<T>
- WinRT 的
👉 这样开发者几乎可以像用 .NET API 一样用 WinRT。
2. WinRT 类型系统核心概念
- WinRT 类型系统是 基于 COM(组件对象模型) 的,但比传统 COM 友好得多。
- 它只支持一些基础类型(
int,string,bool,Guid,DateTime等),不直接暴露复杂的 CLR 特性(比如Nullable<T>)。 - CLR 通过 类型适配 自动完成“对接”。
3. 框架投影(Framework Projections)
框架投影就是 .NET Framework / .NET Core 在背后做的“翻译”。
例如:
- 当你调用
Windows.Storage.StorageFile.OpenAsync(),CLR 会自动把它投影成Task<Stream>,这样用await即可。
4. 调用异步 WinRT API
WinRT 的异步 API 基本都是基于 IAsyncAction 或 IAsyncOperation<T>,而在 C# 中我们直接用 async/await。
示例(Unity 下 UWP 插件交互):
using System;
using System.Threading.Tasks;
using Windows.Storage;
public class WinRTInteropExample
{
public async Task<string> ReadFileAsync(string fileName)
{
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri($"ms-appx:///{fileName}"));
string text = await FileIO.ReadTextAsync(file);
return text;
}
}
在 Unity 的 UWP 导出项目中,你可以直接用 await 调 WinRT API,而不用关心底层 IAsyncOperation<T>。
5. WinRT 流与 .NET 流互操作
- WinRT 流:
IRandomAccessStream - .NET 流:
Stream
CLR 提供了适配器:
WindowsRuntimeStreamExtensions.AsStream()WindowsRuntimeStreamExtensions.AsRandomAccessStream()
using Windows.Storage.Streams;
using System.IO;
IRandomAccessStream winrtStream = await file.OpenAsync(FileAccessMode.Read);
Stream dotNetStream = winrtStream.AsStream();
6. CLR 与 WinRT 间传递数据块
WinRT 常见的场景是 IBuffer,而在 .NET 中我们用 byte[]。
转换方式:
IBuffer.AsStream()WindowsRuntimeBufferExtensions.ToArray()
这样可以高效处理大块数据(比如视频帧、网络传输数据)。
7. 在 C# 中定义 WinRT 组件
不仅可以调用 WinRT API,还可以在 C# 中 编写 WinRT 组件,供其他语言(比如 C++/JavaScript)调用。
定义规则:
- 只能使用 WinRT 支持的类型(不能直接用
Nullable<T>、Tuple、dynamic)。 - 类必须
public sealed。
示例:
public sealed class MathHelper
{
public int Add(int a, int b) => a + b;
}
这样编译后就能在 C++ 或 JS 中被调用。
总结
本章的核心一句话:
CLR Projection 是桥梁,帮我们在 C# 世界中“无痛”调用 WinRT API,而开发者几乎感知不到差异。
主要关注的几个实践点:
- 理解 CLR Projection 规则(异步/集合/流)。
- 学会
async/await调 WinRT API。 - 知道如何在 C# 中定义 WinRT 组件供外部调用。
Unity 面试题(含解析)
Q1:Unity UWP 平台下,如何从 WinRT API 获取文件内容?
- 答案:使用
StorageFile+FileIO.ReadTextAsync,在 C# 中用await调用。
Q2:WinRT 的 IAsyncOperation<T> 在 .NET 中映射成什么?
- 答案:投影为
Task<T>,支持await。
Q3:在 Unity 中如何把 IRandomAccessStream 转换为 .NET Stream?
- 答案:使用
WindowsRuntimeStreamExtensions.AsStream()。
Q4:能否在 Unity(C#)中定义 WinRT 组件并让 C++ 调用?
- 答案:可以,类必须
public sealed,并且只使用 WinRT 支持的类型。
Q5:WinRT 与 .NET 在集合类型上的典型投影规则有哪些?
- 答案:
IVector<T>→IList<T>IMap<K,V>→IDictionary<K,V>IAsyncAction→Task
作者:世纪末的魔术师
出处:https://www.cnblogs.com/Firepad-magic/
Unity最受欢迎插件推荐:点击查看
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

浙公网安备 33010602011771号