【问题标题】:Cannot use ICommand in Portable Class Libary für .NET 4.5, W8, WP8.1 and SL5无法在 .NET 4.5、W8、WP8.1 和 SL5 的便携式类库中使用 ICommand
【发布时间】:2014-05-06 06:15:41
【问题描述】:

我想为 .NET 4.5、Windows 8、Windows Phone 8.1 和 Silverlight 5 创建一个 PCL,但是在检查所有这些平台时我无法使用 ICommand,尽管根据 @987654321 它们都应该支持它@。

重现步骤:

  • 使用 .NET 4.5、Windows 8 和 Silverlight 5 创建 PCL 项目
  • 创建一个实现 ICommand 的类并生成成员
  • 构建成功

  • 在项目设置中添加 Windows Phone 8.1

  • 构建失败(找不到 System.Windows)
  • 如果您删除 Silverlight 或 WP,它可以工作,但同时处于活动状态则不能。

这是错误吗?还是我错过了什么?

【问题讨论】:

标签: .net silverlight windows-phone-8 portable-class-library


【解决方案1】:

不幸的是,我们无法在面向 Silverlight 5 和 Windows Phone 8.1 的 PCL 中支持 ICommand(以及其他 ViewModel 类型,例如 ObservableCollection)。我建议从 PCL 中删除对 SL5 的支持,并通过非便携式库支持该平台。

【讨论】:

  • 如果您花一点时间准确地解释为什么您不能支持它,我们可能会少很多关于 PCL 的问题。 SO 不是论坛。
  • @HansPassant 我们无法支持它的原因与 PCL 如何实现的技术细节有关,大多数开发人员不需要知道或关心这些。问题是这些类型位于 Silverlight 上的 System.Windows.dll 中,但该 DLL 在 Windows Phone 上具有 Windows Phone Silverlight UI 堆栈,它被阻止加载到 Windows Phone XAML 应用程序中(因为它们具有不同的 UI 堆栈)。
  • @DanielPlaisted:我知道这个答案已经有一年了,但是 OP 不能利用“NuGet bait and switch”技术吗?事实上,2014 年 5 月写的一篇博客专门有你评论如何实现这一点! dotnetbyexample.blogspot.com/2014/05/…
【解决方案2】:

我相信您可以在这里完成的最佳解决方案是创建一个共享项目并将所有代码放入其中(需要 VS2013.2+),然后为除 SL5 之外的所有内容创建一个 PCL(配置文件 259),然后是SL5 类库(都具有对共享项目的共享引用)。这将使您能够针对所有平台(但不幸的是,需要两个空程序集来支持通用平台)。

@DanielPlaisted 有关 MS 是否会将非常通用的类型(如 ICommand)重构为较少特定于平台的程序集/命名空间的任何输入? (抱歉问,但你似乎有内幕)。

【讨论】:

  • 我正在考虑更多,因为我不太喜欢这个解决方案。我把我的工作放在这里:git.acrotech.io/acrotech.portableviewmodel.commands 基本上这个想法是创建一个通用可移植命令库(Profile 344),它不提供 System.Windows.Input.ICommand 支持,而是提供 ICommand 的镜像兼容性副本。然后在支持将命令绑定到可移植 ICommand 接口的共享项目(引用所有启用 WPF 的平台)中另外提供子类按钮控件。欢迎反馈
【解决方案3】:

虽然这个问题已经存在一年了,但我遇到了一篇有助于解决这个问题的博客文章:http://dotnetbyexample.blogspot.com/2014/05/writing-behaviors-in-pcl-for-windows.html -- 该博客还包含一个下载示例,因此您可以检查其内部工作原理。该博客使用IBehavior 接口,但概念相同。


基本上,该技术称为“NuGet bait and switch”;您需要创建一个 NuGet 包,其中包含一个 PCL 库和一个特定于平台的库(每个平台一个)。

假设您的 PCL 将被称为“AwesomeMvvm”。你需要:

  • AwesomeMvvm(可移植类库)
  • AwesomeMvvm.Silverlight
  • AwesomeMvvm.Windows81
  • ...

当您尝试在可移植类库 (PCL) 中使用 ICommand 接口时,您将收到一条错误消息,指出 Cannot resolve symbol ICommand。要解决这个问题,只需创建一个接口,确保它位于同一命名空间System.Windows.Input 中。您的可移植类库现在可以编译了!

现在您的可移植类库已编译完成,请创建特定于平台的库并向它们添加对可移植类库的引用。这些库中的每一个只需要一个包含TypeForwardedToAttribute 作为程序集级属性的代码文件:

[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Windows.Input.ICommand))]

最后一步是创建一个包含可移植类库以及每个特定于平台的库的单个 NuGet 包。如果你做的一切都正确,从你的 NuGet 提要中添加一个引用,一切都应该正常工作。 NuGet 将尽可能首选特定于平台的库,每个库都依赖于可移植类库。诀窍在于,在运行时它将使用 ICommand 的本机版本,因为您指定将可移植类库版本转发到特定于平台的版本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多