假设我在每个平台上定义了一个分部类,它定义了一个"初始化"方法,并从我的共享上下文中调用该方法.

我在Android和Windows平台上定义了那个分部类(相同的类名和命名空间).

但由于它的Mac和iOS实现都有相同的代码,我不想重复定义它(在Mac和iOS平台文件夹上).

我遵循了这个指南:https://github.com/dotnet/docs-maui/blob/main/docs/platform-integration/configure-multi-targeting.md

在它的帮助下,我应用了"基于文件夹的多目标",并创建了一个"MaciOS"平台文件夹,在那里定义了我的分部类.

问题是,我的共享上下文表明,iOS和Mac平台上没有实现.这是有道理的,因为iOS和Mac文件夹是空的,但MaciOS文件夹是has级的.

甚至,如果我在"MaciOS"文件夹中打开我的分部类实现,我也没有智能感知,而且Visual Studio也没有说明当前的平台.取而代之的是,它写着"其他文件".

如何在不使用条件编译、不重复代码的情况下共享Mac&iOS代码?

编辑: 我的"基于文件夹的多目标定位"是这样的:

<!-- Android -->
<ItemGroup Condition="$(TargetFramework.StartsWith('net8.0-android')) != true">
    <Compile Remove="**\Android\**\*.cs" />
    <None Include="**\Android\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>

<!-- Both iOS and Mac Catalyst -->
<ItemGroup Condition="$(TargetFramework.StartsWith('net8.0-ios')) != true AND $(TargetFramework.StartsWith('net8.0-maccatalyst')) != true">
    <Compile Remove="**\MaciOS\**\*.cs" />
    <None Include="**\MaciOS\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>

<!-- iOS -->
<ItemGroup Condition="$(TargetFramework.StartsWith('net8.0-ios')) != true">
    <Compile Remove="**\iOS\**\*.cs" />
    <None Include="**\iOS\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>

<!-- Mac Catalyst -->
<ItemGroup Condition="$(TargetFramework.StartsWith('net8.0-maccatalyst')) != true">
    <Compile Remove="**\MacCatalyst\**\*.cs" />
    <None Include="**\MacCatalyst\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>

<!-- Windows -->
<ItemGroup Condition="$(TargetFramework.Contains('-windows')) != true">
    <Compile Remove="**\Windows\**\*.cs" />
    <None Include="**\Windows\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>

推荐答案

由于到目前为止您还没有提供有关当前多目标设置的任何细节,我将提供一个更一般的答案,但我会try 根据您的描述来解决问题.

Multi-targeting approaches

关于多目标,在.NET Maui中有两个选项:

  1. 使用特定于平台的文件夹的基于文件夹的多目标
  2. 使用特定文件名约定的基于文件名的多目标

Folder-based multi-targeting

基于文件夹的多目标有两种类型:内置文件夹和自定义文件夹.

内置目标平台文件夹

第一个模板直接内置在任何新的.NET Maui应用程序项目中(前提是您使用其中一个模板).

在这里,一切都已经配置好了,并且项目的.csproj文件不包含任何条件项组.这就是YourProject/Platforms/下预定义的特定于平台的文件夹的用途.在任何新的.NET Maui项目中,您都会发现以下文件夹 struct :

YourProject
|- Platforms
   |- Android
      |- MyAwesomeFeature.cs
   |- iOS
      |- MyAwesomeFeature.cs
   |- MacCatalyst
      |- MyAwesomeFeature.cs
   |- Windows
      |- MyAwesomeFeature.cs
   |- Tizen
      |- MyAwesomeFeature.cs

在这里,除了将特定于平台的实现放在适当的文件夹中之外,您不需要做任何事情--不需要进一步的配置或条件编译.

这样做的缺点是,您不能通过创建新的目标平台文件夹来简单地添加不同的平台或组合平台的实现.毛伊岛不认识他们,也不承认他们.例如,以下是not种可能性,它们将导致您所描述的您所面临的问题:

YourProject
|- Platforms
   |- Android
      |- MyAwesomeFeature.cs
   |- iOS
   |- MacCatalyst
   |- Windows
      |- MyAwesomeFeature.cs
   |- Tizen
      |- MyAwesomeFeature.cs
   |- MaciOS
      |- MyAwesomeFeature.cs

根据您提供的有限信息,这很可能是您try 过的.

自定义平台文件夹

基于文件夹的多目标的第二种形式需要您进行配置,例如,通过指定要使用的文件夹 struct 的约定.

您可以在项目中的任何其他位置指定您自己的特定于平台的实现文件夹,而不是使用内置文件夹,例如:

YourProject
|- Platforms
|- MyAwesomeFeature
   |- Android
      |- MyAwesomeFeature.cs
   |- MaciOS
      |- MyAwesomeFeature.cs
   |- Windows
      |- MyAwesomeFeature.cs

请注意,我使用的不是标准的YourProject/Platforms/文件夹,而是定制的YourProject/MyAwesomeFeature/文件夹(就在YourProject下面).

为了实现这一点,您可以在.csproj中设置条件物料组(如official documentation中所述):

<!-- Folder-based: Both iOS and Mac Catalyst -->
<ItemGroup Condition="$(TargetFramework.StartsWith('net8.0-ios')) != true AND $(TargetFramework.StartsWith('net8.0-maccatalyst')) != true">
    <Compile Remove="**\MaciOS\**\*.cs" />
    <None Include="**\MaciOS\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>

<!-- Folder-based: Android -->
<ItemGroup Condition="$(TargetFramework.StartsWith('net8.0-android'))">
    <Compile Remove="**\Android\**\*.cs" />
    <None Include="**\Android\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>

<!-- Folder-based: Windows -->
<ItemGroup Condition="$(TargetFramework.StartsWith('net8.0-windows'))">
    <Compile Remove="**\Windows\**\*.cs" />
    <None Include="**\Windows\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>

现在,使用这种方法,您可以共享iOS和MacCatalyst的实现-在某个特定于功能的文件夹中,该文件夹不在默认的内置Platforms文件夹中.

Filename-based multi-targeting

或者,您可以使用基于文件名的多目标,这通常更易于导航和理解,但这取决于您正在使用的功能或API的复杂程度.

在这种情况下,您不会根据文件夹名进行筛选,而是根据文件名进行筛选.您的文件夹 struct 可能如下所示,带有以下文件名:

YourProject
|- MyAwesomeFeature
   |- MyAwesomeFeature.android.cs
   |- MyAwesomeFeature.macios.cs
   |- MyAwesomeFeature.windows.cs

在这里,实现文件都在同一个文件夹中,但它们有不同的后缀,而它们的类名和命名空间声明是相同的.

为此,您需要设置以下条件物料组:

<!-- Filename-based: Both iOS and Mac Catalyst -->
<ItemGroup Condition="$(TargetFramework.StartsWith('net8.0-ios')) != true AND $(TargetFramework.StartsWith('net8.0-maccatalyst')) != true">
  <Compile Remove="**\**\*.macios.cs" />
  <None Include="**\**\*.macios.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>

<!-- Filename-based: Android -->
<ItemGroup Condition="$(TargetFramework.StartsWith('net8.0-android')) != true">
  <Compile Remove="**\**\*.android.cs" />
  <None Include="**\**\*.android.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />  
</ItemGroup>

<!-- Filename-based: Windows -->
<ItemGroup Condition="$(TargetFramework.Contains('-windows')) != true">
  <Compile Remove="**\*.windows.cs" />
  <None Include="**\*.windows.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" /> 
</ItemGroup>

Notes

您可以结合使用基于文件夹和基于文件名的方法,但不能将新文件夹添加到内置的Platforms目录中.

您应该 Select 哪个选项取决于您的需要和您的偏好.

对于多目标,并不总是需要使用partial class个声明.仅当存在包含共享部件和特定于平台的部件的整体API时,才需要这样做.

Csharp相关问答推荐

Blazor:计算值或保留为默认值

EF Core Fluent API中定义的多对多关系

为什么EF Core 6会针对null验证Count(*)?

EF Core在请求列表时忽略列,但在按ID获取时包含

Microsoft. VisualBasic. FileIO. FileSystem. MoveFile()对话框有错误?

dotnet集合中内部数组的局部变量副本的用途是什么?'

MudBlazor—MudDataGrid—默认过滤器定义不允许用户修改基本过滤器

与C#中的Zip列表并行

Azure Redis缓存与Entra ID身份验证

如何使用EF Core和.NET 8来upsert到具有多对多关系的表?

N层解决方案上的依赖注入-删除样板

如何将端点(或с匹配请求并判断其路径)添加到BCL?

依赖项注入、工厂方法和处置困境

.NET:从XPath定位原始XML文档中的 node

我找不到ASP.NET Web应用程序(.NET框架).已 Select .NET框架项目和项模板以及此组件(&Q;)

MSI无法将快捷方式添加到启动文件夹

如何从Entity Framework Core中填充ListIInterface

将J数组转换为列表,只保留一个嵌套的JToken

为什么INTEGER在通过反射调用时对空对象返回TRUE,而在INTEGER上调用时返回FALSE?

从列表中跳过和获取条目的优雅方式