Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HybridCache public API #55084

Merged
merged 34 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
35e9cea
initial API cut (post review)
mgravell Apr 10, 2024
12b3a0e
basic API test
mgravell Apr 11, 2024
c5d28d4
prove that the API can be configured
mgravell Apr 11, 2024
20e1cb2
demonstrate serializer/factory configuration working
mgravell Apr 11, 2024
4379647
move to NuGet only to make the build happier
mgravell Apr 11, 2024
d382a7a
defer on trimming
mgravell Apr 11, 2024
e8bc9a9
PR review comments
mgravell Apr 11, 2024
7edddb1
tyop
mgravell Apr 11, 2024
dc622a8
Update src/Caching/Hybrid/src/Runtime/IsExternalInit.cs
mgravell Apr 11, 2024
4920182
return a leased array on netfx
mgravell Apr 11, 2024
8841e97
prefer ForEach to Walk
mgravell Apr 11, 2024
6cbe02e
Update src/Caching/Hybrid/src/Internal/InbuiltTypeSerializer.cs
mgravell Apr 11, 2024
0c0d589
Update src/Caching/Hybrid/src/Internal/DefaultJsonSerializerFactory.cs
mgravell Apr 11, 2024
ef0ad56
Update src/Caching/Hybrid/src/Internal/InbuiltTypeSerializer.cs
mgravell Apr 11, 2024
e28f316
comment nits
mgravell Apr 11, 2024
fbedef4
Merge branch 'marc/hybrid-api' of https://github.com/dotnet/aspnetcor…
mgravell Apr 11, 2024
b49151e
use TimeProvider throughout
mgravell Apr 11, 2024
c2326fd
more nits
mgravell Apr 11, 2024
29dcc2e
regen projects list
mgravell Apr 11, 2024
4ddba7f
TryAdd
mgravell Apr 12, 2024
427601c
clarify intent of null on Remove{Tags|Keys}Async
mgravell Apr 12, 2024
1db2758
Update src/Caching/Hybrid/src/Runtime/HybridCache.cs
mgravell Apr 17, 2024
2945ce0
Update src/Caching/Hybrid/src/Runtime/HybridCache.cs
mgravell Apr 17, 2024
94d9fe1
Update src/Caching/Hybrid/src/Runtime/HybridCache.cs
mgravell Apr 17, 2024
a13e1d3
Update src/Caching/Hybrid/src/Runtime/HybridCache.cs
mgravell Apr 17, 2024
2a77920
Update src/Caching/Hybrid/src/Runtime/HybridCache.cs
mgravell Apr 17, 2024
cee8ddc
Update src/Caching/Hybrid/src/Runtime/HybridCache.cs
mgravell Apr 17, 2024
7989f16
Update src/Caching/Hybrid/src/Runtime/HybridCacheEntryFlags.cs
mgravell Apr 17, 2024
49a477f
Update src/Caching/Hybrid/src/Runtime/HybridCache.cs
mgravell Apr 17, 2024
5f8bcb8
Update src/Caching/Hybrid/src/Runtime/HybridCacheEntryOptions.cs
mgravell Apr 17, 2024
7b32e0f
Update src/Caching/Hybrid/src/Runtime/HybridCache.cs
mgravell Apr 17, 2024
62b4e6f
Update src/Caching/Hybrid/src/Runtime/IBufferDistributedCache.cs
mgravell Apr 17, 2024
c6cdeae
Apply suggestions from code review
mgravell Apr 17, 2024
d624726
more PR feedback
mgravell Apr 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions AspNetCore.sln
Original file line number Diff line number Diff line change
Expand Up @@ -1788,6 +1788,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NotReferencedInWasmCodePack
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Components.WasmRemoteAuthentication", "src\Components\test\testassets\Components.WasmRemoteAuthentication\Components.WasmRemoteAuthentication.csproj", "{8A021D6D-7935-4AB3-BB47-38D4FF9B0D13}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Hybrid", "Hybrid", "{2D64CA23-6E81-488E-A7D3-9BDF87240098}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Caching.Hybrid", "src\Caching\Hybrid\src\Microsoft.Extensions.Caching.Hybrid.csproj", "{2B60E6D3-9E7C-427A-AD4E-BBE9A6D935B9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Caching.Hybrid.Tests", "src\Caching\Hybrid\test\Microsoft.Extensions.Caching.Hybrid.Tests.csproj", "{CF63C942-895A-4F6B-888A-7653D7C4991A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -10789,6 +10795,38 @@ Global
{8A021D6D-7935-4AB3-BB47-38D4FF9B0D13}.Release|x64.Build.0 = Release|Any CPU
{8A021D6D-7935-4AB3-BB47-38D4FF9B0D13}.Release|x86.ActiveCfg = Release|Any CPU
{8A021D6D-7935-4AB3-BB47-38D4FF9B0D13}.Release|x86.Build.0 = Release|Any CPU
{2B60E6D3-9E7C-427A-AD4E-BBE9A6D935B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2B60E6D3-9E7C-427A-AD4E-BBE9A6D935B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2B60E6D3-9E7C-427A-AD4E-BBE9A6D935B9}.Debug|arm64.ActiveCfg = Debug|Any CPU
{2B60E6D3-9E7C-427A-AD4E-BBE9A6D935B9}.Debug|arm64.Build.0 = Debug|Any CPU
{2B60E6D3-9E7C-427A-AD4E-BBE9A6D935B9}.Debug|x64.ActiveCfg = Debug|Any CPU
{2B60E6D3-9E7C-427A-AD4E-BBE9A6D935B9}.Debug|x64.Build.0 = Debug|Any CPU
{2B60E6D3-9E7C-427A-AD4E-BBE9A6D935B9}.Debug|x86.ActiveCfg = Debug|Any CPU
{2B60E6D3-9E7C-427A-AD4E-BBE9A6D935B9}.Debug|x86.Build.0 = Debug|Any CPU
{2B60E6D3-9E7C-427A-AD4E-BBE9A6D935B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2B60E6D3-9E7C-427A-AD4E-BBE9A6D935B9}.Release|Any CPU.Build.0 = Release|Any CPU
{2B60E6D3-9E7C-427A-AD4E-BBE9A6D935B9}.Release|arm64.ActiveCfg = Release|Any CPU
{2B60E6D3-9E7C-427A-AD4E-BBE9A6D935B9}.Release|arm64.Build.0 = Release|Any CPU
{2B60E6D3-9E7C-427A-AD4E-BBE9A6D935B9}.Release|x64.ActiveCfg = Release|Any CPU
{2B60E6D3-9E7C-427A-AD4E-BBE9A6D935B9}.Release|x64.Build.0 = Release|Any CPU
{2B60E6D3-9E7C-427A-AD4E-BBE9A6D935B9}.Release|x86.ActiveCfg = Release|Any CPU
{2B60E6D3-9E7C-427A-AD4E-BBE9A6D935B9}.Release|x86.Build.0 = Release|Any CPU
{CF63C942-895A-4F6B-888A-7653D7C4991A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CF63C942-895A-4F6B-888A-7653D7C4991A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CF63C942-895A-4F6B-888A-7653D7C4991A}.Debug|arm64.ActiveCfg = Debug|Any CPU
{CF63C942-895A-4F6B-888A-7653D7C4991A}.Debug|arm64.Build.0 = Debug|Any CPU
{CF63C942-895A-4F6B-888A-7653D7C4991A}.Debug|x64.ActiveCfg = Debug|Any CPU
{CF63C942-895A-4F6B-888A-7653D7C4991A}.Debug|x64.Build.0 = Debug|Any CPU
{CF63C942-895A-4F6B-888A-7653D7C4991A}.Debug|x86.ActiveCfg = Debug|Any CPU
{CF63C942-895A-4F6B-888A-7653D7C4991A}.Debug|x86.Build.0 = Debug|Any CPU
{CF63C942-895A-4F6B-888A-7653D7C4991A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CF63C942-895A-4F6B-888A-7653D7C4991A}.Release|Any CPU.Build.0 = Release|Any CPU
{CF63C942-895A-4F6B-888A-7653D7C4991A}.Release|arm64.ActiveCfg = Release|Any CPU
{CF63C942-895A-4F6B-888A-7653D7C4991A}.Release|arm64.Build.0 = Release|Any CPU
{CF63C942-895A-4F6B-888A-7653D7C4991A}.Release|x64.ActiveCfg = Release|Any CPU
{CF63C942-895A-4F6B-888A-7653D7C4991A}.Release|x64.Build.0 = Release|Any CPU
{CF63C942-895A-4F6B-888A-7653D7C4991A}.Release|x86.ActiveCfg = Release|Any CPU
{CF63C942-895A-4F6B-888A-7653D7C4991A}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -11672,6 +11710,9 @@ Global
{15D08EA7-8C63-45FB-8B4D-C5F8E43B433E} = {05A169C7-4F20-4516-B10A-B13C5649D346}
{433F91E4-E39D-4EB0-B798-2998B3969A2C} = {6126DCE4-9692-4EE2-B240-C65743572995}
{8A021D6D-7935-4AB3-BB47-38D4FF9B0D13} = {6126DCE4-9692-4EE2-B240-C65743572995}
{2D64CA23-6E81-488E-A7D3-9BDF87240098} = {0F39820F-F4A5-41C6-9809-D79B68F032EF}
{2B60E6D3-9E7C-427A-AD4E-BBE9A6D935B9} = {2D64CA23-6E81-488E-A7D3-9BDF87240098}
{CF63C942-895A-4F6B-888A-7653D7C4991A} = {2D64CA23-6E81-488E-A7D3-9BDF87240098}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3E8720B3-DBDD-498C-B383-2CC32A054E8F}
Expand Down
1 change: 1 addition & 0 deletions eng/ProjectReferences.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
-->
<Project>
<ItemGroup>
<ProjectReferenceProvider Include="Microsoft.Extensions.Caching.Hybrid" ProjectPath="$(RepoRoot)src\Caching\Hybrid\src\Microsoft.Extensions.Caching.Hybrid.csproj" />
<ProjectReferenceProvider Include="Microsoft.Extensions.Caching.SqlServer" ProjectPath="$(RepoRoot)src\Caching\SqlServer\src\Microsoft.Extensions.Caching.SqlServer.csproj" />
<ProjectReferenceProvider Include="Microsoft.Extensions.Caching.StackExchangeRedis" ProjectPath="$(RepoRoot)src\Caching\StackExchangeRedis\src\Microsoft.Extensions.Caching.StackExchangeRedis.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore" ProjectPath="$(RepoRoot)src\DefaultBuilder\src\Microsoft.AspNetCore.csproj" />
Expand Down
1 change: 1 addition & 0 deletions eng/ShippingAssemblies.props
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
<AspNetCoreShippingAssembly Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" />
<AspNetCoreShippingAssembly Include="Microsoft.Extensions.Diagnostics.HealthChecks" />
<AspNetCoreShippingAssembly Include="Microsoft.Extensions.Features" />
<AspNetCoreShippingAssembly Include="Microsoft.Extensions.Caching.Hybrid" />
<AspNetCoreShippingAssembly Include="Microsoft.Extensions.Caching.SqlServer" />
<AspNetCoreShippingAssembly Include="Microsoft.Extensions.Caching.StackExchangeRedis" />
<AspNetCoreShippingAssembly Include="Microsoft.AspNetCore.JsonPatch" />
Expand Down
1 change: 1 addition & 0 deletions eng/TrimmableProjects.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
-->
<Project>
<ItemGroup>
<TrimmableProject Include="Microsoft.Extensions.Caching.Hybrid" />
<TrimmableProject Include="Microsoft.AspNetCore" />
<TrimmableProject Include="Microsoft.AspNetCore.DataProtection.Abstractions" />
<TrimmableProject Include="Microsoft.AspNetCore.Cryptography.Internal" />
Expand Down
2 changes: 2 additions & 0 deletions src/Caching/Caching.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
"solution": {
"path": "..\\..\\AspNetCore.sln",
"projects": [
"src\\Caching\\Hybrid\\src\\Microsoft.Extensions.Caching.Hybrid.csproj",
"src\\Caching\\Hybrid\\test\\Microsoft.Extensions.Caching.Hybrid.Tests.csproj",
"src\\Caching\\SqlServer\\src\\Microsoft.Extensions.Caching.SqlServer.csproj",
"src\\Caching\\SqlServer\\test\\Microsoft.Extensions.Caching.SqlServer.Tests.csproj",
"src\\Caching\\StackExchangeRedis\\src\\Microsoft.Extensions.Caching.StackExchangeRedis.csproj",
Expand Down
64 changes: 64 additions & 0 deletions src/Caching/Hybrid/src/HybridCacheBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;

namespace Microsoft.Extensions.Caching.Hybrid;

/// <summary>
/// Configuration extension methods for <see cref="IHybridCacheBuilder"/> / <see cref="HybridCache"/>
/// </summary>
public static class HybridCacheBuilderExtensions
{
/// <summary>
/// Serialize values of type <typeparamref name="T"/> with the specified serializer from <paramref name="serializer"/>
/// </summary>
public static IHybridCacheBuilder WithSerializer<T>(this IHybridCacheBuilder builder, IHybridCacheSerializer<T> serializer)
{
builder.Services.AddSingleton<IHybridCacheSerializer<T>>(serializer);
return builder;
}

/// <summary>
/// Serialize values of type <typeparamref name="T"/> with the serializer of type <typeparamref name="TImplementation"/>
/// </summary>
public static IHybridCacheBuilder WithSerializer<T,
#if NET5_0_OR_GREATER
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
#endif
TImplementation>(this IHybridCacheBuilder builder)
where TImplementation : class, IHybridCacheSerializer<T>
{
builder.Services.AddSingleton<IHybridCacheSerializer<T>, TImplementation>();
return builder;
}

/// <summary>
/// Add <paramref name="factory"/> as an additional serializer factory, which can provide serializers for multiple types
/// </summary>
public static IHybridCacheBuilder WithSerializerFactory(this IHybridCacheBuilder builder, IHybridCacheSerializerFactory factory)
{
builder.Services.AddSingleton<IHybridCacheSerializerFactory>(factory);
return builder;
}

/// <summary>
/// Add a factory of type <typeparamref name="TImplementation"/> as an additional serializer factory, which can provide serializers for multiple types
/// </summary>
public static IHybridCacheBuilder WithSerializerFactory<
#if NET5_0_OR_GREATER
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
#endif
TImplementation>(this IHybridCacheBuilder builder)
where TImplementation : class, IHybridCacheSerializerFactory
{
builder.Services.AddSingleton<IHybridCacheSerializerFactory, TImplementation>();
return builder;
}
}
46 changes: 46 additions & 0 deletions src/Caching/Hybrid/src/HybridCacheOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Microsoft.Extensions.Caching.Hybrid;

/// <summary>
/// Options for configuring the default <see cref="HybridCache"/> implementation
/// </summary>
public class HybridCacheOptions
{
/// <summary>
/// Default global options to be applied to <see cref="HybridCache"/> operations; if options are
/// specified at the individual call level, the non-null values are merged (with the per-call
/// options being used in preference to the global options). If no value is specified for a given
/// option (globally or per-call), the implementation may choose a reasonable default.
/// </summary>
public HybridCacheEntryOptions? DefaultEntryOptions { get; set; }

/// <summary>
/// Disallow compression for this <see cref="HybridCache"/> instance
/// </summary>
public bool DisableCompression { get; set; }

/// <summary>
/// The maximum size of cache items; attempts to store values over this size will be logged
/// and the value will not be stored in cache.
/// </summary>
public long MaximumPayloadBytes { get; set; } = 1 << 20; // 1MiB

/// <summary>
/// The maximum permitted length (in characters) of keys; attempts to use keys over this size will be logged.
/// </summary>
public int MaximumKeyLength { get; set; } = 1024; // characters

/// <summary>
/// Use "tags" data as dimensions on metric reporting; if enabled, care should be used to ensure that
/// tags do not contain data that should not be visible in metrics systems.
/// </summary>
public bool ReportTagMetrics { get; set; }
}
64 changes: 64 additions & 0 deletions src/Caching/Hybrid/src/HybridCacheServiceExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Hybrid.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Internal;

namespace Microsoft.Extensions.Caching.Hybrid;

/// <summary>
/// Configuration extension methods for <see cref="HybridCache"/>
/// </summary>
public static class HybridCacheServiceExtensions
{
/// <summary>
/// Adds support for multi-tier caching services
/// </summary>
/// <returns>A builder instance that allows further configuration of the <see cref="HybridCache"/> system</returns>
public static IHybridCacheBuilder AddHybridCache(this IServiceCollection services, Action<HybridCacheOptions> setupAction)
{
#if NET7_0_OR_GREATER
ArgumentNullException.ThrowIfNull(setupAction);
#else
_ = setupAction ?? throw new ArgumentNullException(nameof(setupAction));
#endif
AddHybridCache(services);
services.Configure(setupAction);
return new HybridCacheBuilder(services);
}

/// <summary>
/// Adds support for multi-tier caching services
/// </summary>
/// <returns>A builder instance that allows further configuration of the <see cref="HybridCache"/> system</returns>
public static IHybridCacheBuilder AddHybridCache(this IServiceCollection services)
{
#if NET7_0_OR_GREATER
ArgumentNullException.ThrowIfNull(services);
#else
_ = services ?? throw new ArgumentNullException(nameof(services));
#endif

#if NET8_0_OR_GREATER
services.TryAddSingleton(TimeProvider.System);
#else
services.TryAddSingleton<ISystemClock, SystemClock>();
#endif
services.AddOptions();
services.AddMemoryCache();
services.AddDistributedMemoryCache(); // we need a backend; use in-proc by default
services.AddSingleton<IHybridCacheSerializerFactory, DefaultJsonSerializerFactory>();
services.AddSingleton<IHybridCacheSerializer<string>>(InbuiltTypeSerializer.Instance);
services.AddSingleton<IHybridCacheSerializer<byte[]>>(InbuiltTypeSerializer.Instance);
services.AddSingleton<HybridCache, DefaultHybridCache>();
return new HybridCacheBuilder(services);
}
}
27 changes: 27 additions & 0 deletions src/Caching/Hybrid/src/IHybridCacheBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;

namespace Microsoft.Extensions.Caching.Hybrid;

/// <summary>
/// Helper API for configuring <see cref="HybridCache"/>.
/// </summary>
public interface IHybridCacheBuilder
{
/// <summary>
/// Gets the services collection associated with this instance.
/// </summary>
IServiceCollection Services { get; }
}

internal sealed class HybridCacheBuilder(IServiceCollection services) : IHybridCacheBuilder
{
public IServiceCollection Services { get; } = services;
}
60 changes: 60 additions & 0 deletions src/Caching/Hybrid/src/Internal/DefaultHybridCache.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

namespace Microsoft.Extensions.Caching.Hybrid.Internal;

/// <summary>
/// The inbuilt ASP.NET implementation of <see cref="HybridCache"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ASP.NET Core*

/// </summary>
internal sealed class DefaultHybridCache : HybridCache
{
private readonly IDistributedCache backendCache;
private readonly IServiceProvider services;
private readonly HybridCacheOptions options;
public DefaultHybridCache(IOptions<HybridCacheOptions> options, IDistributedCache backendCache, IServiceProvider services)
{
this.backendCache = backendCache ?? throw new ArgumentNullException(nameof(backendCache));
this.services = services ?? throw new ArgumentNullException(nameof(services));
this.options = options.Value;
}
internal HybridCacheOptions Options => options;

public override ValueTask<T> GetOrCreateAsync<TState, T>(string key, TState state, Func<TState, CancellationToken, ValueTask<T>> underlyingDataCallback, HybridCacheEntryOptions? options = null, IReadOnlyCollection<string>? tags = null, CancellationToken token = default)
=> underlyingDataCallback(state, token); // pass-thru without caching for initial API pass

public override ValueTask RemoveKeyAsync(string key, CancellationToken token = default)
=> default; // no cache, nothing to remove

public override ValueTask RemoveTagAsync(string tag, CancellationToken token = default)
=> default; // no cache, nothing to remove

public override ValueTask SetAsync<T>(string key, T value, HybridCacheEntryOptions? options = null, IReadOnlyCollection<string>? tags = null, CancellationToken token = default)
=> default; // no cache, nothing to set

internal IHybridCacheSerializer<T> GetSerializer<T>()
{
// unused API, primarily intended to show configuration is working;
// the real version would memoize the result
var service = services.GetServices<IHybridCacheSerializer<T>>().LastOrDefault();
if (service is null)
{
foreach (var factory in services.GetServices<IHybridCacheSerializerFactory>())
{
if (factory.TryCreateSerializer<T>(out var current))
{
service = current;
}
}
}
return service ?? throw new InvalidOperationException("No serializer configured for type: " + typeof(T).Name);
}
}
37 changes: 37 additions & 0 deletions src/Caching/Hybrid/src/Internal/DefaultJsonSerializerFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Buffers;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;

namespace Microsoft.Extensions.Caching.Hybrid.Internal;
internal sealed class DefaultJsonSerializerFactory : IHybridCacheSerializerFactory
{
public bool TryCreateSerializer<T>([NotNullWhen(true)] out IHybridCacheSerializer<T>? serializer)
{
// no restriction
serializer = new DefaultJsonSerializer<T>();
return true;
}

internal sealed class DefaultJsonSerializer<T> : IHybridCacheSerializer<T>
{
T IHybridCacheSerializer<T>.Deserialize(ReadOnlySequence<byte> source)
{
var reader = new Utf8JsonReader(source);
#pragma warning disable IL2026, IL3050 // AOT bits
return JsonSerializer.Deserialize<T>(ref reader)!;
#pragma warning restore IL2026, IL3050
}

void IHybridCacheSerializer<T>.Serialize(T value, IBufferWriter<byte> target)
{
using var writer = new Utf8JsonWriter(target);
#pragma warning disable IL2026, IL3050 // AOT bits
JsonSerializer.Serialize<T>(writer, value, JsonSerializerOptions.Default);
#pragma warning restore IL2026, IL3050
}
}

}
Loading
Loading