【问题标题】:How to use TypeForwardedTo in Portable Class Libraries?如何在可移植类库中使用 TypeForwardedTo?
【发布时间】:2013-08-20 20:00:33
【问题描述】:

我正在尝试构建一个可移植类库,该类库在可用时使用来自平台的实现。例如,Lazy<T> 在 .NET 4.5、Windows Store Apps、Windows Phone 8 上可用,但在 Windows Phone 7、Silverlight 4 上不可用。当我的 PCL 加载到具有 Lazy<T> 实现的平台之一时,我想用平台的实现。当它在平台上不可用时,我想使用我自己的实现。好像是可以的,因为微软BCL在做,但是我还没想好怎么实现。

我已经读到,通过使用TypeForwardedToAttribute,您可以重定向 PCL 以使用来自平台的实现。我不太确定如何配置我的 Visual Studio 项目以实现此结果。如果 CoreLib 是我的库,并且 ShimLib 包含我对 Lazy<T> 的实现。我在哪里添加 TypeForwardedToAttribute?该属性需要一个实际的类型引用typeof(System.Lazy<>),当Windows Phone 7 以PCL 为目标时,这不起作用。如果我删除 Windows Phone 7,那么我无法将 CoreLib 的引用添加到 ShimLib,因为 ShimLib 不支持 CoreLib 支持的所有平台。我该如何处理?

是的,我知道Lazy<T> 非常容易实现,但这只是一个示例,我的实际情况适用于更多不那么容易实现的类。

【问题讨论】:

  • [TypeForwardedTo] 并没有真正解决底层部署问题。对于 PCL,Microsoft 负责根据平台部署可能包含或不包含 [TypeForwardedTo] 的程序集。您自己的转发课程不会获得相同的帮助。
  • Lazy 如果您忽略LazyThreadSafetyMode,则“超级容易实现”。不用担心,我已经为您提供了保障:Theraot's Lazy<T> for .NET 3.5 or previous 如需替代方案,请参阅LazyNeedle<T>(请报告任何错误)。 完全披露:是的,我是同一个威胁。

标签: c# .net portable-class-library


【解决方案1】:

类型转发的原理思想在this question 和this 文章中有很好的解释,这里不再赘述。然而,总而言之,这个想法是能够重用库 A 无需重新编译,即使它引用了一个 正在被库替换的库 B C。为此,必须修改库 B,以便将引用转发到库 C,这正是 TypeForwardedTo 属性所做的。

这对您有什么帮助?好吧,您可以创建您的 ShimLib 以便它被您的所有项目引用,但使用条件编译和类型转发将其链接到框架库(如果存在)。幸运的是,someone already didthat for you :)

编辑回应 Matt 的评论:你说得对,我忽略了 Theraot 并没有回退到最初的实现。而且我想如果不重新编译,这将很难实现。您可以做的最好的事情可能是遵循this 策略,即为不同的框架版本提供不同的构建配置。这样,您可以有条件地编译TypeForwardedToAttribute。至少,这使您不必重复代码。如果您真的不想分发不同版本的代码,您可以实现 determines the framework version 的引导程序并加载已使用此版本的构建配置编译的程序集版本

【讨论】:

  • 我从概念上了解 TypeForwardedTo 属性是如何工作的,是的,我已经让它在普通程序集中工作。我遇到的问题是将它与便携式类库结合起来。 Theraot 很有趣,但它不是 PCL,并且如果存在,它不会遵循框架的实现。它正在为特定版本的框架创建库。我的目标是 Microsoft.Bcl (nuget.org/packages/Microsoft.Bcl),其中 Phone7 使用 BCL 的可移植 Task 实现,但 Phone8 和 WinRuntime 使用框架的 Task 实现
  • 非常感谢。不同的构建配置很接近,但我无法更改每个配置的 PCL 项目的目标框架属性。无论配置如何,它都会为项目设置一次。如果我无法更改目标框架以排除 WP7,则会出现构建错误,因为编译器无法解析 TypeForwardedTo 属性中的 System.Lazy。也许创建多个生成相同程序集名称的项目是唯一的策略。
  • 也许这篇文章对你有帮助:stackoverflow.com/questions/2923210/…
  • @MattDotson 和 bigge 确实缺少前面提到的后备......事实上你给了我一个想法......我可以制作一个面向 .NET 2.0 的外观程序集(所以您可以从大多数项目中包含它)有一个检测并调用正确的程序集。这增加了开销,但使用它是可选的。你怎么看? (不过,这将需要大量测试)。关于 PCL... 我会讲到的。注意:除了 System.Threading.Tasks,我目前期待以 .NET Compact Framework 为目标(没有具体日期)。
【解决方案2】:

Microsoft.Bcl 通过发送具有相同标识的两个程序集来做到这一点;一个是类型本身,一个是 forward 类型。在针对不支持 Lazy 的平台(包括包含这些平台之一的可移植库组合)时,您可以使用该类型引用该类型。并在使用 Lazy 定位平台时使用 type-forward 引用,这样可以使用针对旧平台构建的库。

请注意,Microsoft.Bcl 有一点您没有的优势。我们发布的程序集与更高版本中已有的程序集具有相同的标识,这意味着当 Windows Phone 7 app 在 Windows Phone 8 上运行时,它们会获得内置版本,而不是垫片库中的一个。你无法模仿这一点,但在你的情况下,这可能是你可以忍受的。

【讨论】:

  • 这正是我想要模仿的,而无法重现 BCL 的身份似乎是要我死的原因。现在对我来说很有意义。 Lazy 只是一个我认为很容易说明的例子。我的实际实现是尝试为 WP7 填充 Windows.Storage API,以便我可以为 WP8、W8 和 WP7 写入一个存储 API。在 W8 上,我希望我的公共 API 公开真实 Windows.Storage 中的类型。在 WP7 上,它们将是我对 StorageFile、StorageFolder 等的实现。
  • 哦,我明白你的问题了。 Windows.Storage 几乎无法模仿。这是一个 WinRT API。 WinRT 受编译器的约束不同于传统的 .NET API,后者在 Windows Phone 7 上无法模仿,因为运行时对此一无所知。相反,我建议使用类似 Daniel Plaisted 的 PCL 存储,它为 IO API 提供包装器:pclstorage.codeplex.com
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-21
  • 1970-01-01
  • 2014-07-10
  • 2017-05-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多