Skip to content

Commit

Permalink
feature: Add maui and use HttpClient (#788)
Browse files Browse the repository at this point in the history
  • Loading branch information
glennawatson authored Jun 25, 2022
1 parent d5f85dc commit da43863
Show file tree
Hide file tree
Showing 30 changed files with 615 additions and 218 deletions.
25 changes: 6 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ settings) as well as cached local data that expires.

Akavache is currently compatible with:

* Xamarin.iOS / Xamarin.Mac
* Xamarin.Android
* .NET 4.5 Desktop (WPF)
* Windows Phone 8.1 Universal Apps
* Xamarin.iOS / Xamarin.Mac / Xamarin.Android / Xamarin.TVOS / Xamarin.WatchOS
* Maui iOS / Mac / Mac Catalyst / Android / TVOS
* .NET 4.6.2 (and above) and .NET 6 Desktop (WPF and WinForms)
* .NET 6.0
* Windows 10 (Universal Windows Platform)
* Tizen 4.0

Expand Down Expand Up @@ -94,27 +94,14 @@ There are four built-in locations that have some magic applied on some systems:

### Platform-specific notes

* **Xamarin.iOS / Xamarin.Mac** - No issues.

* **Xamarin.Android** - No issues.

* **.NET 4.5 Desktop (WPF)** - No issues.

* **Windows Phone 8.1 Universal Apps** - You must mark your application as `x86`
or `ARM`, or else you will get a strange runtime error about SQLitePCL_Raw not
loading correctly. You must *also* ensure that the Microsoft Visual C++ runtime
is added to your project.

* **Windows 10 (Universal Windows Platform)** - You must mark your application as `x86`
or `ARM`, or else you will get a strange runtime error about SQLitePCL_Raw not
loading correctly. You must *also* ensure that the Microsoft Visual C++ runtime
is added to your project.

* **Tizen 4.0** - No issues.

#### Handling Xamarin Linker
#### Handling Xamarin/Maui Linker

There are two options to ensure the Akavache.Sqlite3 dll will not be removed by Xamarin build tools
There are two options to ensure the Akavache.Sqlite3 dll will not be removed by Xamarin and Maui build tools

#### 1) Add a file to reference the types

Expand Down
19 changes: 0 additions & 19 deletions packages/repositories.config

This file was deleted.

35 changes: 33 additions & 2 deletions src/Akavache.Core/Akavache.Core.csproj
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
<Project Sdk="MSBuild.Sdk.Extras">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;Xamarin.iOS10;Xamarin.Mac20;Xamarin.TVOS10;MonoAndroid11.0;tizen40;net6.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0;netstandard2.1;Xamarin.iOS10;Xamarin.Mac20;Xamarin.TVOS10;MonoAndroid11.0;tizen40;net6.0;net6.0-android;net6.0-ios;net6.0-tvos;net6.0-macos;net6.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net462;uap10.0.16299;net6.0-windows</TargetFrameworks>
<AssemblyName>Akavache.Core</AssemblyName>
<RootNamespace>Akavache</RootNamespace>
<Description>An asynchronous, persistent key-value store for desktop and mobile applications on .NET</Description>
<PackageId>akavache.core</PackageId>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
Expand All @@ -17,6 +16,10 @@
<PackageReference Include="Splat" Version="14.*" />
</ItemGroup>

<ItemGroup>
<Using Remove="Foundation" />
</ItemGroup>

<ItemGroup>
<Compile Remove="Platforms\**\*.cs" />
<None Include="Platforms\**\*.cs" />
Expand All @@ -41,27 +44,55 @@
<Reference Include="System.Runtime.Serialization" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('net6.0-ios')) ">
<Compile Include="Platforms\apple-common\**\*.cs" />
<Compile Include="Platforms\xamarin-mobile\**\*.cs" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('Xamarin.TVOS')) ">
<Compile Include="Platforms\apple-common\**\*.cs" />
<Compile Include="Platforms\xamarin-mobile\**\*.cs" />
<Reference Include="System.Runtime.Serialization" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('net6.0-tvos')) ">
<Compile Include="Platforms\apple-common\**\*.cs" />
<Compile Include="Platforms\xamarin-mobile\**\*.cs" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('net6.0-maccatalyst')) ">
<Compile Include="Platforms\apple-common\**\*.cs" />
<Compile Include="Platforms\xamarin-mobile\**\*.cs" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('Xamarin.Mac')) ">
<Compile Include="Platforms\apple-common\**\*.cs" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="netstandard" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('net6.0-macos')) ">
<Compile Include="Platforms\apple-common\**\*.cs" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('MonoAndroid')) ">
<Compile Include="Platforms\android\**\*.cs" />
<Compile Include="Platforms\xamarin-mobile\**\*.cs" />
<Reference Include="System.Runtime.Serialization" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('net6.0-android')) ">
<Compile Include="Platforms\android\**\*.cs" />
<Compile Include="Platforms\xamarin-mobile\**\*.cs" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('tizen40')) ">
<Compile Include="Platforms\tizen\**\*.cs" />
<Compile Include="Platforms\xamarin-mobile\**\*.cs" />
</ItemGroup>

<ItemGroup>
<None Remove="Platforms\shared\DefaultAkavacheHttpClientFactory.cs" />
</ItemGroup>

</Project>
230 changes: 230 additions & 0 deletions src/Akavache.Core/BlobCache/BlobCache.cs.orig
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System.Diagnostics.CodeAnalysis;
using System.Reactive.Threading.Tasks;

using Newtonsoft.Json.Bson;

using Splat;

namespace Akavache;

/// <summary>
/// A class which represents a blobbed cache.
/// </summary>
public static class BlobCache
{
private static string? _applicationName;
private static IBlobCache? _localMachine;
private static IBlobCache? _userAccount;
private static ISecureBlobCache? _secure;
private static bool _shutdownRequested;

private static IScheduler? _taskPoolOverride;

[ThreadStatic]
private static IBlobCache? _unitTestLocalMachine;

[ThreadStatic]
private static IBlobCache? _unitTestUserAccount;

[ThreadStatic]
private static ISecureBlobCache? _unitTestSecure;

static BlobCache()
{
Locator.RegisterResolverCallbackChanged(() =>
{
if (Locator.CurrentMutable is null)
{
return;
}

Locator.CurrentMutable.InitializeAkavache(Locator.Current);
});

InMemory = new InMemoryBlobCache(Scheduler.Default);
}

/// <summary>
/// Gets or sets your application's name. Set this at startup, this defines where
/// your data will be stored (usually at %AppData%\[ApplicationName]).
/// </summary>
[SuppressMessage("Design", "CA1065: Properties should not fire exceptions.", Justification = "Extreme non standard case.")]
public static string ApplicationName
{
<<<<<<< HEAD
get
{
if (_applicationName is null)
{
throw new InvalidOperationException("Make sure to set BlobCache.ApplicationName on startup");
}

return _applicationName;
}
=======
get => _applicationName ?? throw new("Make sure to set BlobCache.ApplicationName on startup");
>>>>>>> main

set => _applicationName = value;
}

/// <summary>
/// Gets or sets the local machine cache. Store data here that is unrelated to the
/// user account or shouldn't be uploaded to other machines (i.e.
/// image cache data).
/// </summary>
public static IBlobCache LocalMachine
{
get => _unitTestLocalMachine ?? _localMachine ?? (_shutdownRequested ? new ShutdownBlobCache() : null) ?? Locator.Current.GetService<IBlobCache>("LocalMachine") ?? throw new InvalidOperationException("Unable to resolve LocalMachine cache. Make sure Akavache is initialized properly.");
set
{
if (ModeDetector.InUnitTestRunner())
{
_unitTestLocalMachine = value;
_localMachine ??= value;
}
else
{
_localMachine = value;
}
}
}

/// <summary>
/// Gets or sets the user account cache. Store data here that is associated with
/// the user; in large organizations, this data will be synced to all
/// machines via NT Roaming Profiles.
/// </summary>
public static IBlobCache UserAccount
{
get => _unitTestUserAccount ?? _userAccount ?? (_shutdownRequested ? new ShutdownBlobCache() : null) ?? Locator.Current.GetService<IBlobCache>("UserAccount") ?? throw new InvalidOperationException("Unable to resolve UserAccount cache. Make sure Akavache is initialized properly.");
set
{
if (ModeDetector.InUnitTestRunner())
{
_unitTestUserAccount = value;
_userAccount ??= value;
}
else
{
_userAccount = value;
}
}
}

/// <summary>
/// Gets or sets an IBlobCache that is encrypted - store sensitive data in this
/// cache such as login information.
/// </summary>
public static ISecureBlobCache Secure
{
get => _unitTestSecure ?? _secure ?? (_shutdownRequested ? new ShutdownBlobCache() : null) ?? Locator.Current.GetService<ISecureBlobCache>() ?? throw new InvalidOperationException("Unable to resolve Secure cache. Make sure Akavache is initialized properly.");
set
{
if (ModeDetector.InUnitTestRunner())
{
_unitTestSecure = value;
_secure ??= value;
}
else
{
_secure = value;
}
}
}

/// <summary>
/// Gets or sets an IBlobCache that simply stores data in memory. Data stored in
/// this cache will be lost when the application restarts.
/// </summary>
public static ISecureBlobCache InMemory { get; set; }

/// <summary>
/// Gets or sets the DateTimeKind handling for BSON readers to be forced.
/// </summary>
/// <remarks>
/// <para>
/// By default, <see cref="BsonReader"/> uses a <see cref="DateTimeKind"/> of <see cref="DateTimeKind.Local"/> and <see cref="BsonWriter"/>
/// uses <see cref="DateTimeKind.Utc"/>. Thus, DateTimes are serialized as UTC but deserialized as local time. To force BSON readers to
/// use some other <c>DateTimeKind</c>, you can set this value.
/// </para>
/// </remarks>
public static DateTimeKind? ForcedDateTimeKind { get; set; }

/// <summary>
/// Gets or sets the Scheduler used for task pools.
/// </summary>
public static IScheduler TaskpoolScheduler
{
get => _taskPoolOverride ?? Locator.Current.GetService<IScheduler>("Taskpool") ?? TaskPoolScheduler.Default;
set => _taskPoolOverride = value;
}

/// <summary>
/// Makes sure that the system has been initialized.
/// </summary>
public static void EnsureInitialized() =>

// NB: This method doesn't actually do anything, it just ensures
// that the static constructor runs
LogHost.Default.Debug("Initializing Akavache");

/// <summary>
/// This method shuts down all of the blob caches. Make sure call it
/// on app exit and await / Wait() on it.
/// </summary>
/// <returns>A Task representing when all caches have finished shutting
/// down.</returns>
public static Task Shutdown()
{
_shutdownRequested = true;
var toDispose = new[] { LocalMachine, UserAccount, Secure, InMemory, };

var ret = toDispose.Select(x =>
{
x.Dispose();
return x.Shutdown;
}).Merge().ToList().Select(_ => Unit.Default);

return ret.ToTask();
}

private class ShutdownBlobCache : ISecureBlobCache
{
IObservable<Unit> IBlobCache.Shutdown => Observable.Return(Unit.Default);

public IScheduler Scheduler => System.Reactive.Concurrency.Scheduler.Immediate;

/// <inheritdoc />
public DateTimeKind? ForcedDateTimeKind
{
get => null;
set { }
}

public void Dispose()
{
}

public IObservable<Unit> Insert(string key, byte[] data, DateTimeOffset? absoluteExpiration = null) => Observable.Empty<Unit>();

public IObservable<byte[]> Get(string key) => Observable.Empty<byte[]>();

public IObservable<IEnumerable<string>> GetAllKeys() => Observable.Empty<IEnumerable<string>>();

public IObservable<DateTimeOffset?> GetCreatedAt(string key) => Observable.Empty<DateTimeOffset?>();

public IObservable<Unit> Flush() => Observable.Empty<Unit>();

public IObservable<Unit> Invalidate(string key) => Observable.Empty<Unit>();

public IObservable<Unit> InvalidateAll() => Observable.Empty<Unit>();

public IObservable<Unit> Vacuum() => Observable.Empty<Unit>();
}
}
2 changes: 1 addition & 1 deletion src/Akavache.Core/DependencyResolverMixin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public static void InitializeAkavache(this IMutableDependencyResolver resolver,

if (fdr?.AssemblyQualifiedName is null)
{
throw new($"Cannot find valid assembly name for the {nameof(DependencyResolverMixin)} class.");
throw new InvalidOperationException($"Cannot find valid assembly name for the {nameof(DependencyResolverMixin)} class.");
}

var assemblyName = new AssemblyName(
Expand Down
Loading

0 comments on commit da43863

Please sign in to comment.