键盘快捷键

在章节间导航

S/ 在书中搜索

? 显示此帮助

Esc 隐藏此帮助

如何为 WinRT 集合接口创建现成的集合?

除了自己实现 COM 接口之外,windows crate 还为常见的 WinRT 集合接口提供了现成的集合实现。实现 WinRT 集合接口可能非常具有挑战性,因此在许多情况下,这应该能为您省去很多工作。需要使用 implement 功能才能使用这些现成的实现。

让我们考虑几个示例。WinRT 集合接口都定义在 Foundation::Collections 模块中,因此我们首先添加对 windows crate 的依赖,并包含 Foundation_Collections 功能

[dependencies.windows]
version = "0.52"
features = [
    "implement",
    "Foundation_Collections",
]

创建集合就像在现有 VecBTreeMap 上使用 TryFrom 特征一样简单,具体取决于集合的类型

WinRT 接口来自
IIterable<T>Vec<T::Default>
IVectorView<T>Vec<T::Default>
IMapView<K, V>BTreeMap<K::Default, V::Default>

因此,如果您需要 i32 值的 IIterable 实现,您可以按如下方式创建它

use windows::{core::*, Foundation::Collections::*};

fn main() -> Result<()> {
    let collection = IIterable::<i32>::try_from(vec![1, 2, 3])?;

    for n in collection {
        println!("{n}");
    }

    Ok(())
}

生成的 collection 将实现所有专用的 IIterable<i32> 方法。

您是否注意到上表中的 T::Default?挑战在于,当 WinRT 集合包含可为空类型时(与 i32 不同),集合必须必然支持能够表达此情况的后端实现。对于此类可为空或引用类型,Default 关联类型只是将 T 替换为 Option<T>

让我们考虑一个稍微更刻意的例子。在这里,我们将创建一个 IMapView,其中字符串用作键,接口用作值。WinRT 字符串不可为空,但接口可为空。WinRT 字符串在 windows crate 中由 HSTRING 表示,对于接口,我们将仅使用 IStringable 实现

#![allow(unused)]
fn main() {
use windows::Foundation::*;

#[implement(IStringable)]
struct Value(&'static str);

impl IStringable_Impl for Value {
    fn ToString(&self) -> Result<HSTRING> {
        Ok(self.0.into())
    }
}
}

我们现在可以按如下方式创建 std 集合

#![allow(unused)]
fn main() {
use std::collections::*;

let map = BTreeMap::from([
    ("hello".into(), Some(Value("HELLO").into())),
    ("hello".into(), Some(Value("WORLD").into())),
]);
}

Rust 编译器自然会推断出确切的类型:BTreeMap<HSTRING, Option<IStringable>>

最后,我们可以使用 TryInto 特征将该 BTreeMap 包装在 WinRT 集合中,如下所示

#![allow(unused)]
fn main() {
let map: IMapView<HSTRING, IStringable> = map.try_into()?;

for pair in map {
    println!("{} - {}", pair.Key()?, pair.Value()?.ToString()?);
}
}