简体   繁体   中英

Partial platform specific methods in .NET MAUI

I'm trying to implement plattform specific partial method in .NET MAUI to get the connection string for the database.

In the "main application":

namespace TestApp.DL;

public partial class BaseHandler
{
    public partial string GetDBPath();

    private string GetCnnPath() 
    {
        var dbPath = GetDBPath();
        var cnnPath = $"Data Source={dbPath}";

        return cnnPath;
    }

    ...
}

in the platform folders in the project:

在此处输入图像描述

where each contain the plattform specific implementation:

namespace TestApp.DL;

// All the code in this file is only included on Android.
public partial class BaseHandler
{
    public string GetDBPath()
    {
        var dbName = "com.mycompany.mydatabase.db";
        return Android.App.Application.Context.GetDatabasePath(dbName).AbsolutePath;
    }
}

...but I keep getting "Error CS8795: Partial method 'BaseHandler.GetDBPath()' must have an implementation part because it has accessibility modifiers. (CS8795)". It seems like the platform specific files are not seen by the compiler? Note, they are in a separate assembly project from the main application but that should be ok I guess, given that the fwk created the folders for me?

When you struggle with partials you can keep using partial classes, but avoid using partial methods. This is especially true when creating maui libs, were this approach tends to break, while in maui apps the compilation works fine.

The "quick fix solution", all partial classes must use same namespace obviously:

Shared code, you would want to change NET6_0 to NET7_0 whatever you are using:

public partial class BaseHandler
{
    private string GetCnnPath() 
    {
        var dbPath = GetDBPath();
        var cnnPath = $"Data Source={dbPath}";

        return cnnPath;
    }

#if (NET6_0 && !ANDROID && !IOS && !MACCATALYST && !WINDOWS && !TIZEN)

        public string GetDBPath()
        {
            throw new PlatformNotSupportedException();
        }
#endif
}

Your platform specific code in platform Platforms/Android:

public partial class BaseHandler
{
    public string GetDBPath()
    {
        var dbName = "com.mycompany.mydatabase.db";
        return Android.App.Application.Context.GetDatabasePath(dbName).AbsolutePath;
    }
}

First of all, your implementation must use the partial keyword as well:

namespace TestApp.DL;

// All the code in this file is only included on Android.
public partial class BaseHandler
{
    public partial string GetDBPath()
    {
        var dbName = "com.mycompany.mydatabase.db";
        return Android.App.Application.Context.GetDatabasePath(dbName).AbsolutePath;
    }
}

Then, you should make sure that you're following the guidelines for multi-targeting: https://learn.microsoft.com/en-us/do.net/maui/platform-integration/configure-multi-targeting#configure-folder-based-multi-targeting

You'll need to update your.csproj file with the following:

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

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

<!-- Mac Catalyst -->
<ItemGroup Condition="$(TargetFramework.StartsWith('net6.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>

Without this, you would see another compiler error because you can only provide one body for any partial method declaration. You need to provide platform specific implementations for each platform and disable the compilation of the ones that are not needed or you can add a default implementation, but then you need file-based multi-targeting instead of platform-based multi-targeting (or a combination of both).

I've had a similar problem already and solved it here: MAUI: How to use partial classes for platform specific implementations together with.net7.0 as TargetFramework in the SingleProject?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM