c# - 如何创建一个项目来为支持 iOS、Android 和 UWP 的 Xamarin Forms 创建 Nuget 包?

标签 c# android ios xamarin xamarin.forms

感觉这个世界上没有人做过。我找不到任何关于如何创建它的教程或帮助。我想做的是创建我自己的插件,比如说将通知添加到 Xamarin 表单,这将在 Android、iOS 和 UWP 上运行。每次提到这个我都会看到提到创建一个多平台库,但这只适用于 Mac 的 VS,不包括 UWP。 VS2017 不包含多平台库模板。我希望它像所有其他 xamarin 插件一样工作,您可以将它从 nuget 下载到您的所有项目中,并且您可以访问平台实现和共享代码。

我在 stackoverflow 上看到其他问题提出这个问题,但它们没有得到回答或链接已失效且在 VS2017 上不起作用。

如何创建可在多个项目之间共享的 xamarin 表单库?我怎样才能把它变成一个 nuget 包,所以它是一个无脑安装并且它可以正常工作?越详细越好,因为它会帮助我看到谷歌搜索这个问题但没有找到答案的每个人。

请记住,这不是像 Microsoft 教程所示那样适用于 Visual Studio Mac,而是适用于具有最新更新的 VS 2017 社区版。

编辑 1:

为了补充下面的一些评论,我还尝试了 James 创建的这个插件,但它甚至无法像在他的 youtube 视频中那样工作:https://www.youtube.com/watch?v=MSwH8NrtVCk&feature=youtu.be

生成的项目没有任何文件夹。

最佳答案

这正是 MvvmCross、ReactiveUI 和其他框架所做的。因此,声称世界上没有人这样做是一种天马行空的想象。

一种方法是创建一个多目标库,请注意 Visual Studio for Mac 尚不喜欢这些项目,您在创建和开发此类库时会遇到问题。但是,如果您只在 Windows Visual Studio 2017 和更新版本上开发,则可以很好地支持这些类型的项目。

您可以从在 VS 中创建一个 .NET Standard 库开始,这将为您提供一个包含 Class1 的单个 .cs 文件的项目,然后将其删除。

如果您编辑 .csproj 文件,您将在文件顶部看到一个 PropertyGroup,其中包含一个名为 TargetFramework 的属性。将其更改为 TargetFrameworks 并列出您想要定位的所有所需框架:

<PropertyGroup
    <TargetFrameworks>netstandard2.0;Xamarin.iOS10;MonoAndroid81;uap10.0.16299</TargetFrameworks>

如果您希望在多目标库中轻松获得支持,我建议您为您的项目 SDK 切换到 MSBuildSDKExtras,因为它将处理针对 Xamarin 平台的许多怪癖。它将为您的项目添加必要的属性以完成所有这些工作。

因此 .csproj 文件的第一行必须如下所示:

<Project Sdk="MSBuild.Sdk.Extras/1.6.68">

现在您需要指定平台特定代码所在的文件夹。我通常做的是创建一个 platforms 文件夹,其中包含 androidiosuap 文件夹,并认为其余的代码平台独立于 common

<ItemGroup>
    <Compile Remove="platforms\**\*.cs" />
    <None Include="platforms\**\*.cs" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) ">
    <Compile Include="platforms\common\**\*.cs" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('Xamarin.iOS')) ">
    <Compile Include="platforms\ios\**\*.cs" />
    <Compile Include="platforms\common\**\*.cs" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('MonoAndroid')) ">
    <Compile Include="platforms\android\**\*.cs" />
    <Compile Include="platforms\common\**\*.cs" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('uap')) ">
    <Compile Include="platforms\uap\**\*.cs" />
    <Compile Include="platforms\common\**\*.cs" />
</ItemGroup>

为了从这个多目标库很好地创建 NuGet 包,我通常在解决方案的根目录中添加一个 Directory.build.props 文件,我在其中指定包的属性:

<Project>
  <PropertyGroup>
    <Company>Cheesebaron</Company>
    <Copyright>Copyright © Cheesebaron</Copyright>
    <RepositoryUrl>https://github.com/cheeesebaron/cool-stuff</RepositoryUrl>
    <Authors>Cheesebaron</Authors>
    <Owners>Cheesebaron</Owners>
    <PackageReleaseNotes />
    <PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
    <PublishRepositoryUrl>true</PublishRepositoryUrl>
    <RepositoryType>git</RepositoryType>
    <Product>$(AssemblyName) ($(TargetFramework))</Product>
    <NeutralLanguage>en</NeutralLanguage>

    <LangVersion>latest</LangVersion>
    <NoWarn>$(NoWarn);1591;1701;1702;1705;VSX1000;NU1603</NoWarn>
    <GenerateDocumentationFile Condition=" '$(Configuration)' == 'Release' ">true</GenerateDocumentationFile>
    <GeneratePackageOnBuild Condition=" '$(Configuration)' == 'Release' and '$(IsTestProject)' != 'true'">true</GeneratePackageOnBuild>

    <Platform>AnyCPU</Platform>
    <DebugType>portable</DebugType>
    <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
    <EmbedUntrackedSources>true</EmbedUntrackedSources>

    <IsTestProject>$(MSBuildProjectName.Contains('UnitTests'))</IsTestProject>
  </PropertyGroup>
</Project>

我还添加了一个 Directory.build.targets 文件来定义不同平台的常量:

<Project>
  <PropertyGroup Condition="$(TargetFramework.StartsWith('netstandard'))">
    <DefineConstants>$(DefineConstants);NETSTANDARD;PORTABLE</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition="$(TargetFramework.StartsWith('Xamarin.iOS'))">
    <DefineConstants>$(DefineConstants);MONO;UIKIT;COCOA;IOS</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition="$(TargetFramework.StartsWith('MonoAndroid'))">
    <DefineConstants>$(DefineConstants);MONO;ANDROID</DefineConstants>
    <MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
    <AndroidResgenClass>Resource</AndroidResgenClass>
    <AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
  </PropertyGroup>
</Project>

如果您的目标是 Android,您可能还需要添加:

<None Include="Resources\*.cs" />
<Compile Remove="Resources\*.cs" />

到您的 .csproj 文件中的第一个 ItemGroup 并添加如下内容:

<AndroidResource Include="Resources\**\*.xml" SubType="Designer" Generator="MSBuild:UpdateAndroidResources" />
<AndroidResource Include="Resources\**\*.axml" SubType="Designer" Generator="MSBuild:UpdateAndroidResources" />

到 Android ItemGroup 以正确更新 Android 资源。

在 Visual Studio 中添加文件可能有点棘手,它通常会将前几个文件添加到错误的位置,直到您在所有平台特定文件夹中都有内容。但是,只要文件正确放置在我们定义的结构中,您就不需要 .csproj 文件中的任何其他内容。

您可以在此处查看多目标库的示例:

https://github.com/MvvmCross/MvvmCross/blob/develop/MvvmCross/MvvmCross.csproj https://github.com/MvvmCross/MvvmCross/blob/develop/Directory.build.props https://github.com/MvvmCross/MvvmCross/blob/develop/Directory.build.targets

ReactiveUI 同样如此:

https://github.com/reactiveui/ReactiveUI/blob/master/src/ReactiveUI/ReactiveUI.csproj

到目前为止,上手并不是特别容易,但使用起来还不错。 替代方法是 .NET Standard 库和添加诱饵切换模式的特定于平台的库。

关于c# - 如何创建一个项目来为支持 iOS、Android 和 UWP 的 Xamarin Forms 创建 Nuget 包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55291602/

相关文章:

php - 使用 json rereiver php mysql 填充 fragment 中的 ListView

ios - iOS 应用程序工具中的其他部分是什么?

c# - .NET 4 中任务并行库的连接池

c# - 未知服务器标签 'CR:CrystalReportViewer'

java - 安卓应用程序 : Can I show products different in a 7 inch tablet from a 10 inch tablet?

android - 无论哪个 Activity 或服务首先在 android 中运行,如何始终在 android 中运行某些代码?

C# 如何从 calendar.SelectedDate 中以 dd/MM/yyyy 格式获取日期

javascript - 在 Angular 中将对象数组传递给 POST

ios - 使用 Xcode 7 本地化 iOS 框架字符串和资源

ios - 如何将 UITextView 的光标移动到 TOUCHED LOCATION?