Xamarin的可移植库-.NET Standard与UWP

时间:2018-07-23 22:39:55

标签: .net xamarin uwp

我有以下情况:

  • Assembly X是我正在构建的Xamarin类库。它针对iOS,Android和.NET Standard 2.0。
  • Assembly X在Xamarin.Essentials中引用了可移植性API。
  • Xamarin.Essentials面向iOS,Android,.NET Standard和UWP(uap10.0.16299)。
  • 现在,有人想使用Assembly X来构建Windows 10应用程序。
  • 由于它们在Windows 10中,因此我希望他们获得Xamarin.Essentials的UWP版本。但是在我看来,它总是替代使用.NET Standard版本,大概是因为X正是使用此版本。结果是他们没有获得Xamarin.Essentials提供的Windows特定行为。

有什么办法解决吗?还是我也必须构建X的UWP版本?到目前为止,我一直避免这样做的原因是,我将拥有一些只能在Windows上构建的目标,而另一些只能在Mac上构建的目标。

1 个答案:

答案 0 :(得分:0)

并非必须以特定于平台的方式构建自定义.NetStd程序集。您针对Xamarin.Essentials .NetStd参考程序集进行编译,然后针对与平台相关的Xamarin.Essentials程序集进行绑定,包括与平台相关的代码。

因此,在运行时,您的自定义.NetStd程序集中的类型将被转发/调用到您的应用中已包含的Xamarin.Essentials平台特定的程序集中。

因此,在包含.NetStd的自定义Xamarin.Essentials程序集中,将有一个外部程序集定义:

.assembly extern Xamarin.Essentials
{
  .ver 1:0:0:0
}

然后在同一.NetStd程序集中,您的代码将调用该程序集中存在的类型,即:OpenAppPackageFileAsync

IL_0030:  call [System.Threading.Tasks]System.Threading.Tasks.Task`1<[System.IO]System.IO.Stream> [Xamarin.Essentials]Xamarin.Essentials.FileSystem::OpenAppPackageFileAsync(string)

注意:对于Essentials,它不使用DI / Interfaces来调用依赖于平台的代码,方法OpenAppPackageFileAsync调用PlatformOpenAppPackageFileAsync方法,而该方法将包括平台-每个平台相关程序集中的特定代码。在其基于.NetStd的参考Assembly方法中,它抛出NotImplementedInReferenceAssemblyException,因为没有通用/通用基于.NetStd的框架代码实现加载只读应用程序捆绑的Android / iOS / UWP文件,即:

.method private hidebysig static [System.Threading.Tasks]System.Threading.Tasks.Task`1<[System.IO]System.IO.Stream>
          PlatformOpenAppPackageFileAsync(string filename) cil managed
  {
    // Code size       6 (0x6)
    .maxstack  8
    IL_0000:  newobj     instance void Xamarin.Essentials.NotImplementedInReferenceAssemblyException::.ctor()
    IL_0005:  throw
  } // end of method FileSystem::PlatformOpenAppPackageFileAsync

现在,当打包/捆绑依赖于平台的应用程序(例如在本例中为Android)时,您将不会处理/包括Essentials参考程序集,而是平台特定的版本。

Xamarin.Essentials.dll程序集的Android版本为此PlatformOpenAppPackageFileAsync方法提供了此功能:

.method private hidebysig static [mscorlib]System.Threading.Tasks.Task`1<[mscorlib]System.IO.Stream>
          PlatformOpenAppPackageFileAsync(string filename) cil managed
  {
    // Code size       70 (0x46)
    .maxstack  3
    .locals init ([mscorlib]System.Threading.Tasks.Task`1<[mscorlib]System.IO.Stream> V_0,
             [Mono.Android]Java.IO.FileNotFoundException V_1)
    IL_0000:  ldarg.0
    IL_0001:  brtrue.s   IL_000e
    ~~~~
    .try
    {
      IL_001d:  call       [Mono.Android]Android.Content.Context Xamarin.Essentials.Platform::get_AppContext()
      IL_0022:  callvirt   instance [Mono.Android]Android.Content.Res.AssetManager [Mono.Android]Android.Content.Context::get_Assets()
      IL_0027:  ldarg.0
      IL_0028:  callvirt   instance [mscorlib]System.IO.Stream [Mono.Android]Android.Content.Res.AssetManager::Open(string)
      IL_002d:  call       [mscorlib]System.Threading.Tasks.Task`1<!!0> [mscorlib]System.Threading.Tasks.Task::FromResult<[mscorlib]System.IO.Stream>(!!0)
      IL_0032:  stloc.0
      IL_0033:  leave.s    IL_0044
      ~~~