Skip to content

Commit bc46847

Browse files
authoredJun 2, 2024
Merge v1.2.0 (ZiggyCreatures#254)
* Add support for keyed services + tests * Disable backplane traces by default * Make activity root when receiving a backplane message * Better traces for incoming backplane messages * Snapshots testing update for v1.1.0 * Updated xml docs
1 parent 53fea69 commit bc46847

27 files changed

+1197
-139
lines changed
 

‎src/ZiggyCreatures.FusionCache.OpenTelemetry/FusionCacheTracesInstrumentationOptions.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ public class FusionCacheTracesInstrumentationOptions
1616
public bool IncludeDistributedLevel { get; set; } = true;
1717

1818
/// <summary>
19-
/// Include traces for the backplane. (default: <see langword="true"/>)
19+
/// Include traces for the backplane. (default: <see langword="false"/>)
2020
/// </summary>
21-
public bool IncludeBackplane { get; set; } = true;
21+
public bool IncludeBackplane { get; set; } = false;
2222
}
2323
}

‎src/ZiggyCreatures.FusionCache.OpenTelemetry/ZiggyCreatures.FusionCache.OpenTelemetry.xml

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/ZiggyCreatures.FusionCache/FusionCache.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -874,7 +874,9 @@ internal bool MustAwaitBackplaneOperations(FusionCacheEntryOptions options)
874874
if (_logger?.IsEnabled(LogLevel.Trace) ?? false)
875875
_logger.Log(LogLevel.Trace, "FUSION [N={CacheName} I={CacheInstanceId}] (O={CacheOperationId} K={CacheKey}): updating memory entry from distributed entry", CacheName, InstanceId, operationId, cacheKey);
876876

877-
memoryEntry.UpdateFromDistributedEntry(distributedEntry);
877+
878+
_mca.UpdateEntryFromDistributedEntry(operationId, cacheKey, memoryEntry, distributedEntry);
879+
//memoryEntry.UpdateFromDistributedEntry(distributedEntry);
878880

879881
if (_logger?.IsEnabled(LogLevel.Trace) ?? false)
880882
_logger.Log(LogLevel.Trace, "FUSION [N={CacheName} I={CacheInstanceId}] (O={CacheOperationId} K={CacheKey}): memory entry updated from distributed", CacheName, InstanceId, operationId, cacheKey);

‎src/ZiggyCreatures.FusionCache/FusionCacheBuilderExtMethods.cs

+316-73
Large diffs are not rendered by default.

‎src/ZiggyCreatures.FusionCache/Internals/Backplane/BackplaneAccessor.cs

+23
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Diagnostics;
23
using System.Threading.Tasks;
34
using Microsoft.Extensions.Logging;
45
using ZiggyCreatures.Caching.Fusion.Backplane;
@@ -229,8 +230,17 @@ private async ValueTask HandleIncomingMessageAsync(BackplaneMessage message)
229230
}
230231

231232
// ACTIVITY
233+
234+
// TEMP SWAP THE CURRENT ACTIVITY TO HAVE THE NEW ONE AS ROOT
235+
var previous = Activity.Current;
236+
Activity.Current = null;
237+
232238
using var activity = Activities.SourceBackplane.StartActivityWithCommonTags(Activities.Names.BackplaneReceive, _options.CacheName, _options.InstanceId!, message.CacheKey!, operationId);
233239
activity?.SetTag("fusioncache.backplane.message_action", message.Action.ToString());
240+
activity?.SetTag("fusioncache.backplane.message_source_id", message.SourceId);
241+
242+
// REVERT THE PREVIOUS CURRENT ACTIVITY
243+
Activity.Current = previous;
234244

235245
// EVENT
236246
_events.OnMessageReceived(operationId, message);
@@ -241,6 +251,10 @@ private async ValueTask HandleIncomingMessageAsync(BackplaneMessage message)
241251
if (_logger?.IsEnabled(_options.BackplaneErrorsLogLevel) ?? false)
242252
_logger.Log(_options.BackplaneErrorsLogLevel, "FUSION [N={CacheName} I={CacheInstanceId}] (O={CacheOperationId} K={CacheKey}): [BP] an invalid backplane notification has been received from remote cache {RemoteCacheInstanceId} (A={Action}, T={InstantTimestamp})", _cache.CacheName, _cache.InstanceId, operationId, message.CacheKey, message.SourceId, message.Action, message.Timestamp);
243253

254+
// ACTIVITY
255+
activity?.SetStatus(ActivityStatusCode.Error, Activities.EventNames.BackplaneIncomingMessageInvalid);
256+
activity?.Dispose();
257+
244258
return;
245259
}
246260

@@ -252,6 +266,10 @@ private async ValueTask HandleIncomingMessageAsync(BackplaneMessage message)
252266
if (_logger?.IsEnabled(LogLevel.Debug) ?? false)
253267
_logger.Log(LogLevel.Debug, "FUSION [N={CacheName} I={CacheInstanceId}] (O={CacheOperationId} K={CacheKey}): [BP] a backplane notification has been received from remote cache {RemoteCacheInstanceId}, but has been ignored since there is a pending one in the auto-recovery queue which is more recent", _cache.CacheName, _cache.InstanceId, operationId, message.CacheKey, message.SourceId);
254268

269+
// ACTIVITY
270+
activity?.SetStatus(ActivityStatusCode.Error, Activities.EventNames.BackplaneIncomingMessageConflicts);
271+
activity?.Dispose();
272+
255273
return;
256274
}
257275
}
@@ -284,6 +302,11 @@ private async ValueTask HandleIncomingMessageAsync(BackplaneMessage message)
284302
// HANDLE UNKNOWN: DO NOTHING
285303
if (_logger?.IsEnabled(_options.BackplaneErrorsLogLevel) ?? false)
286304
_logger.Log(_options.BackplaneErrorsLogLevel, "FUSION [N={CacheName} I={CacheInstanceId}] (O={CacheOperationId} K={CacheKey}): [BP] an backplane notification has been received from remote cache {RemoteCacheInstanceId} for an unknown action {Action}", _cache.CacheName, _cache.InstanceId, operationId, message.CacheKey, message.SourceId, message.Action);
305+
306+
// ACTIVITY
307+
activity?.SetStatus(ActivityStatusCode.Error, Activities.EventNames.BackplaneIncomingMessageUnknownAction);
308+
activity?.Dispose();
309+
287310
break;
288311
}
289312
}

‎src/ZiggyCreatures.FusionCache/Internals/Builder/FusionCacheBuilder.cs

+21-21
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,19 @@ public FusionCacheBuilder(string cacheName, IServiceCollection services)
4040
public IServiceCollection Services { get; }
4141

4242
public bool UseRegisteredLogger { get; set; }
43-
public string? LoggerKeyedServiceName { get; set; }
43+
public object? LoggerServiceKey { get; set; }
4444
public ILogger<FusionCache>? Logger { get; set; }
4545
public Func<IServiceProvider, ILogger<FusionCache>>? LoggerFactory { get; set; }
4646
public bool ThrowIfMissingLogger { get; set; }
4747

4848
public bool UseRegisteredMemoryCache { get; set; }
49-
public string? MemoryCacheKeyedServiceName { get; set; }
49+
public object? MemoryCacheServiceKey { get; set; }
5050
public IMemoryCache? MemoryCache { get; set; }
5151
public Func<IServiceProvider, IMemoryCache>? MemoryCacheFactory { get; set; }
5252
public bool ThrowIfMissingMemoryCache { get; set; }
5353

5454
public bool UseRegisteredMemoryLocker { get; set; }
55-
public string? MemoryLockerKeyedServiceName { get; set; }
55+
public object? MemoryLockerServiceKey { get; set; }
5656
public IFusionCacheMemoryLocker? MemoryLocker { get; set; }
5757
public Func<IServiceProvider, IFusionCacheMemoryLocker>? MemoryLockerFactory { get; set; }
5858
public bool ThrowIfMissingMemoryLocker { get; set; }
@@ -67,26 +67,26 @@ public FusionCacheBuilder(string cacheName, IServiceCollection services)
6767
public Action<FusionCacheEntryOptions>? SetupDefaultEntryOptionsAction { get; set; }
6868

6969
public bool UseRegisteredSerializer { get; set; }
70-
public string? SerializerKeyedServiceName { get; set; }
70+
public object? SerializerServiceKey { get; set; }
7171
public IFusionCacheSerializer? Serializer { get; set; }
7272
public Func<IServiceProvider, IFusionCacheSerializer>? SerializerFactory { get; set; }
7373
public bool ThrowIfMissingSerializer { get; set; }
7474

7575
public bool UseRegisteredDistributedCache { get; set; }
76-
public string? DistributedCacheKeyedServiceName { get; set; }
76+
public object? DistributedCacheServiceKey { get; set; }
7777
public bool IgnoreRegisteredMemoryDistributedCache { get; set; }
7878
public IDistributedCache? DistributedCache { get; set; }
7979
public Func<IServiceProvider, IDistributedCache>? DistributedCacheFactory { get; set; }
8080
public bool ThrowIfMissingDistributedCache { get; set; }
8181

8282
public bool UseRegisteredBackplane { get; set; }
83-
public string? BackplaneKeyedServiceName { get; set; }
83+
public object? BackplaneServiceKey { get; set; }
8484
public IFusionCacheBackplane? Backplane { get; set; }
8585
public Func<IServiceProvider, IFusionCacheBackplane>? BackplaneFactory { get; set; }
8686
public bool ThrowIfMissingBackplane { get; set; }
8787

8888
public bool UseAllRegisteredPlugins { get; set; }
89-
public string? PluginsKeyedServiceName { get; set; }
89+
public object? PluginsServiceKey { get; set; }
9090
public List<IFusionCachePlugin> Plugins { get; }
9191
public List<Func<IServiceProvider, IFusionCachePlugin>> PluginsFactories { get; }
9292

@@ -155,13 +155,13 @@ public IFusionCache Build(IServiceProvider serviceProvider)
155155

156156
if (UseRegisteredLogger)
157157
{
158-
if (string.IsNullOrWhiteSpace(LoggerKeyedServiceName))
158+
if (LoggerServiceKey is null)
159159
{
160160
logger = serviceProvider.GetService<ILogger<FusionCache>>();
161161
}
162162
else
163163
{
164-
logger = serviceProvider.GetKeyedService<ILogger<FusionCache>>(LoggerKeyedServiceName);
164+
logger = serviceProvider.GetKeyedService<ILogger<FusionCache>>(LoggerServiceKey);
165165
}
166166
}
167167
else if (LoggerFactory is not null)
@@ -183,13 +183,13 @@ public IFusionCache Build(IServiceProvider serviceProvider)
183183

184184
if (UseRegisteredMemoryCache)
185185
{
186-
if (string.IsNullOrWhiteSpace(LoggerKeyedServiceName))
186+
if (MemoryCacheServiceKey is null)
187187
{
188188
memoryCache = serviceProvider.GetService<IMemoryCache>();
189189
}
190190
else
191191
{
192-
memoryCache = serviceProvider.GetKeyedService<IMemoryCache>(MemoryCacheKeyedServiceName);
192+
memoryCache = serviceProvider.GetKeyedService<IMemoryCache>(MemoryCacheServiceKey);
193193
}
194194
}
195195
else if (MemoryCacheFactory is not null)
@@ -211,13 +211,13 @@ public IFusionCache Build(IServiceProvider serviceProvider)
211211

212212
if (UseRegisteredMemoryLocker)
213213
{
214-
if (string.IsNullOrWhiteSpace(MemoryLockerKeyedServiceName))
214+
if (MemoryLockerServiceKey is null)
215215
{
216216
memoryLocker = serviceProvider.GetService<IFusionCacheMemoryLocker>();
217217
}
218218
else
219219
{
220-
memoryLocker = serviceProvider.GetKeyedService<IFusionCacheMemoryLocker>(MemoryLockerKeyedServiceName);
220+
memoryLocker = serviceProvider.GetKeyedService<IFusionCacheMemoryLocker>(MemoryLockerServiceKey);
221221
}
222222
}
223223
else if (MemoryLockerFactory is not null)
@@ -241,13 +241,13 @@ public IFusionCache Build(IServiceProvider serviceProvider)
241241
IDistributedCache? distributedCache;
242242
if (UseRegisteredDistributedCache)
243243
{
244-
if (string.IsNullOrWhiteSpace(DistributedCacheKeyedServiceName))
244+
if (DistributedCacheServiceKey is null)
245245
{
246246
distributedCache = serviceProvider.GetService<IDistributedCache>();
247247
}
248248
else
249249
{
250-
distributedCache = serviceProvider.GetKeyedService<IDistributedCache>(DistributedCacheKeyedServiceName);
250+
distributedCache = serviceProvider.GetKeyedService<IDistributedCache>(DistributedCacheServiceKey);
251251
}
252252

253253
if (IgnoreRegisteredMemoryDistributedCache && distributedCache is MemoryDistributedCache)
@@ -274,13 +274,13 @@ public IFusionCache Build(IServiceProvider serviceProvider)
274274
IFusionCacheSerializer? serializer;
275275
if (UseRegisteredSerializer)
276276
{
277-
if (string.IsNullOrWhiteSpace(SerializerKeyedServiceName))
277+
if (SerializerServiceKey is null)
278278
{
279279
serializer = serviceProvider.GetService<IFusionCacheSerializer>();
280280
}
281281
else
282282
{
283-
serializer = serviceProvider.GetKeyedService<IFusionCacheSerializer>(SerializerKeyedServiceName);
283+
serializer = serviceProvider.GetKeyedService<IFusionCacheSerializer>(SerializerServiceKey);
284284
}
285285
}
286286
else if (SerializerFactory is not null)
@@ -312,13 +312,13 @@ public IFusionCache Build(IServiceProvider serviceProvider)
312312
IFusionCacheBackplane? backplane;
313313
if (UseRegisteredBackplane)
314314
{
315-
if (string.IsNullOrWhiteSpace(BackplaneKeyedServiceName))
315+
if (BackplaneServiceKey is null)
316316
{
317317
backplane = serviceProvider.GetService<IFusionCacheBackplane>();
318318
}
319319
else
320320
{
321-
backplane = serviceProvider.GetKeyedService<IFusionCacheBackplane>(BackplaneKeyedServiceName);
321+
backplane = serviceProvider.GetKeyedService<IFusionCacheBackplane>(BackplaneServiceKey);
322322
}
323323
}
324324
else if (BackplaneFactory is not null)
@@ -348,9 +348,9 @@ public IFusionCache Build(IServiceProvider serviceProvider)
348348
plugins.AddRange(serviceProvider.GetServices<IFusionCachePlugin>());
349349
}
350350

351-
if (string.IsNullOrWhiteSpace(PluginsKeyedServiceName) == false)
351+
if (PluginsServiceKey is not null)
352352
{
353-
plugins.AddRange(serviceProvider.GetKeyedServices<IFusionCachePlugin>(PluginsKeyedServiceName));
353+
plugins.AddRange(serviceProvider.GetKeyedServices<IFusionCachePlugin>(PluginsServiceKey));
354354
}
355355

356356
if (Plugins?.Any() == true)

‎src/ZiggyCreatures.FusionCache/Internals/Diagnostics/Activities.cs

+3
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ internal static class EventNames
4747
{
4848
public const string FactoryBackgroundMove = "factory moved to the background";
4949
public const string FactoryBackgroundMoveNotAllowed = "factory not allowed to be moved to the background";
50+
public const string BackplaneIncomingMessageInvalid = "incoming message invalid";
51+
public const string BackplaneIncomingMessageConflicts = "incoming message with conflicts";
52+
public const string BackplaneIncomingMessageUnknownAction = "incoming message with unknown action";
5053
}
5154

5255
public static IEnumerable<KeyValuePair<string, object?>> GetCommonTags(string? cacheName, string? cacheInstanceId, string? key, string? operationId, CacheLevelKind? levelKind)

‎src/ZiggyCreatures.FusionCache/Internals/Memory/MemoryCacheAccessor.cs

+9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Microsoft.Extensions.Logging;
44
using ZiggyCreatures.Caching.Fusion.Events;
55
using ZiggyCreatures.Caching.Fusion.Internals.Diagnostics;
6+
using ZiggyCreatures.Caching.Fusion.Internals.Distributed;
67

78
namespace ZiggyCreatures.Caching.Fusion.Internals.Memory;
89

@@ -31,6 +32,14 @@ public MemoryCacheAccessor(IMemoryCache? memoryCache, FusionCacheOptions options
3132
private readonly ILogger? _logger;
3233
private readonly FusionCacheMemoryEventsHub _events;
3334

35+
public void UpdateEntryFromDistributedEntry<TValue>(string operationId, string key, FusionCacheMemoryEntry<TValue> memoryEntry, FusionCacheDistributedEntry<TValue> distributedEntry)
36+
{
37+
// ACTIVITY
38+
using var activity = Activities.SourceMemoryLevel.StartActivityWithCommonTags(Activities.Names.MemorySet, _options.CacheName, _options.InstanceId!, key, operationId, CacheLevelKind.Memory);
39+
40+
memoryEntry.UpdateFromDistributedEntry(distributedEntry);
41+
}
42+
3443
public void SetEntry<TValue>(string operationId, string key, IFusionCacheMemoryEntry entry, FusionCacheEntryOptions options, bool skipPhysicalSet = false)
3544
{
3645
// ACTIVITY

‎src/ZiggyCreatures.FusionCache/ZiggyCreatures.FusionCache.csproj

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
<RootNamespace>ZiggyCreatures.Caching.Fusion</RootNamespace>
1010
<DocumentationFile>ZiggyCreatures.FusionCache.xml</DocumentationFile>
1111
<PackageReleaseNotes>
12-
- Add: full support for DI keyed services
12+
- Add: full support for DI keyed services, both registration and resolution
1313
- Add: new PreferSyncSerialization option
14+
- Change: disable backplane traces by default
15+
- Change: backplane traces (observability) are now root
1416
</PackageReleaseNotes>
1517
<EnablePackageValidation>true</EnablePackageValidation>
1618
<PackageValidationBaselineVersion>1.0.0</PackageValidationBaselineVersion>

‎src/ZiggyCreatures.FusionCache/ZiggyCreatures.FusionCache.xml

+229-24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"v":"Sloths are cool!","m":{"e":"2033-07-08T14:53:13.4520833+00:00","f":true,"ea":"2033-06-28T14:53:13.4520833+00:00","et":"MyETagValue","lm":"2033-03-30T14:53:13.4520833+00:00"},"t":638528613274343519}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
Sloths are cool!-��Ψ�ɭ���������" MyETagValue(����Ϋ�߰���̠�
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"v":"Sloths are cool!","m":{"e":"2033-07-08T14:53:13.4520833+00:00","f":true,"ea":"2033-06-28T14:53:13.4520833+00:00","et":"MyETagValue","lm":"2033-03-30T14:53:13.4520833+00:00"},"t":638528613274343519}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"Value":"Sloths are cool!","Metadata":{"LogicalExpiration":"2033-07-08T14:53:13.4520833+00:00","IsFromFailSafe":true,"EagerExpiration":"2033-06-28T14:53:13.4520833+00:00","ETag":"MyETagValue","LastModified":"2033-03-30T14:53:13.4520833+00:00"},"Timestamp":638528613274343519}

‎tests/SerializerPayloadGenerator/SerializerPayloadGenerator.csproj

+15-6
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
</PropertyGroup>
99

1010
<ItemGroup>
11-
<PackageReference Include="ZiggyCreatures.FusionCache.Serialization.CysharpMemoryPack" Version="1.0.0" />
12-
<PackageReference Include="ZiggyCreatures.FusionCache.Serialization.NeueccMessagePack" Version="1.0.0" />
13-
<PackageReference Include="ZiggyCreatures.FusionCache.Serialization.NewtonsoftJson" Version="1.0.0" />
14-
<PackageReference Include="ZiggyCreatures.FusionCache.Serialization.ProtoBufNet" Version="1.0.0" />
15-
<PackageReference Include="ZiggyCreatures.FusionCache.Serialization.ServiceStackJson" Version="1.0.0" />
16-
<PackageReference Include="ZiggyCreatures.FusionCache.Serialization.SystemTextJson" Version="1.0.0" />
11+
<PackageReference Include="ZiggyCreatures.FusionCache.Serialization.CysharpMemoryPack" Version="1.1.0" />
12+
<PackageReference Include="ZiggyCreatures.FusionCache.Serialization.NeueccMessagePack" Version="1.1.0" />
13+
<PackageReference Include="ZiggyCreatures.FusionCache.Serialization.NewtonsoftJson" Version="1.1.0" />
14+
<PackageReference Include="ZiggyCreatures.FusionCache.Serialization.ProtoBufNet" Version="1.1.0" />
15+
<PackageReference Include="ZiggyCreatures.FusionCache.Serialization.ServiceStackJson" Version="1.1.0" />
16+
<PackageReference Include="ZiggyCreatures.FusionCache.Serialization.SystemTextJson" Version="1.1.0" />
1717
</ItemGroup>
1818

1919
<ItemGroup>
@@ -31,4 +31,13 @@
3131
<Content Remove="Samples\fusioncachesystemtextjsonserializer__v1_0_0_0.bin" />
3232
</ItemGroup>
3333

34+
<ItemGroup>
35+
<None Remove="Samples\fusioncachecysharpmemorypackserializer__v1_1_0_0.bin" />
36+
<None Remove="Samples\fusioncacheneueccmessagepackserializer__v1_1_0_0.bin" />
37+
<None Remove="Samples\fusioncachenewtonsoftjsonserializer__v1_1_0_0.bin" />
38+
<None Remove="Samples\fusioncacheprotobufnetserializer__v1_1_0_0.bin" />
39+
<None Remove="Samples\fusioncacheservicestackjsonserializer__v1_1_0_0.bin" />
40+
<None Remove="Samples\fusioncachesystemtextjsonserializer__v1_1_0_0.bin" />
41+
</ItemGroup>
42+
3443
</Project>

‎tests/ZiggyCreatures.FusionCache.Playground/Scenarios/OpenTelemetryScenario.cs

+31-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Linq;
66
using System.Text;
77
using System.Threading.Tasks;
8+
using Honeycomb.OpenTelemetry;
89
using Microsoft.Extensions.Caching.Distributed;
910
using Microsoft.Extensions.Caching.Memory;
1011
using Microsoft.Extensions.DependencyInjection;
@@ -165,7 +166,7 @@ public static async Task RunAsync()
165166

166167
//app.Run();
167168

168-
var cachesCount = 1;
169+
var cachesCount = 3;
169170
var caches = new List<IFusionCache>();
170171
IFusionCache fusionCache;
171172

@@ -206,6 +207,9 @@ public static async Task RunAsync()
206207
},
207208
};
208209

210+
// WARNING: THIS IS JUST FOR TESTING PURPOSES, DON'T DO THIS IN PRODUCTION
211+
options.SetInstanceId($"CACHE-OTLP-{i}");
212+
209213
var cache = new FusionCache(options);
210214

211215
// DISTRIBUTED CACHE
@@ -232,6 +236,32 @@ public static async Task RunAsync()
232236

233237
fusionCache = caches[0];
234238

239+
//for (int i = 0; i < 10; i++)
240+
//{
241+
// var x = i;
242+
// await fusionCache.GetOrSetAsync<long>($"foo-{i}", async _ => { await Task.Delay(Random.Shared.Next(200)); return x; });
243+
//}
244+
245+
//await Task.Delay(1_000);
246+
247+
//for (int i = 0; i < 10; i++)
248+
//{
249+
// var x = i;
250+
// await caches[i % 2].SetAsync<long>($"foo-{i}", DateTime.UtcNow.Ticks);
251+
//}
252+
253+
//await Task.Delay(1_000);
254+
255+
//for (int i = 0; i < 10; i++)
256+
//{
257+
// var x = i;
258+
// await caches[1 - (i % 2)].SetAsync<long>($"foo-{i}", DateTime.UtcNow.Ticks);
259+
//}
260+
//return;
261+
262+
263+
264+
235265
using (var activity = Source.StartActivity("Top-Level Action (GetOrDefault)"))
236266
{
237267
var tmp0 = await fusionCache.GetOrDefaultAsync<int>("foo", 123);

‎tests/ZiggyCreatures.FusionCache.Tests/DependencyInjectionTests.cs

+188-9
Original file line numberDiff line numberDiff line change
@@ -1033,8 +1033,9 @@ public void CanActAsKeyedService()
10331033
;
10341034

10351035
// BAZ: 3 HOURS DURATION + FAIL-SAFE + BACKPLANE (POST-SETUP)
1036+
var bazServiceKey = new SimpleServiceKey(123);
10361037
services.AddFusionCache("BazCache")
1037-
.AsKeyedService()
1038+
.AsKeyedService(bazServiceKey)
10381039
.WithOptions(opt =>
10391040
{
10401041
opt.BackplaneChannelPrefix = "CCC";
@@ -1070,7 +1071,9 @@ public void CanActAsKeyedService()
10701071
var barCache2 = serviceProvider.GetRequiredKeyedService<IFusionCache>("BarCache");
10711072

10721073
var bazCache = cacheProvider.GetCache("BazCache");
1073-
var bazCache2 = serviceProvider.GetRequiredKeyedService<IFusionCache>("BazCache");
1074+
var bazCache1 = serviceProvider.GetKeyedService<IFusionCache>("BazCache");
1075+
var bazCache2 = serviceProvider.GetRequiredKeyedService<IFusionCache>(bazServiceKey);
1076+
var bazCache3 = serviceProvider.GetRequiredKeyedService<IFusionCache>(new SimpleServiceKey(123));
10741077

10751078
var quxCache = cacheProvider.GetCache("QuxCache");
10761079
var quxCache2 = serviceProvider.GetRequiredKeyedService<IFusionCache>("QuxCache");
@@ -1082,40 +1085,144 @@ public void CanActAsKeyedService()
10821085
Assert.Equal(barCache, barCache2);
10831086

10841087
Assert.NotNull(bazCache);
1088+
Assert.Null(bazCache1);
10851089
Assert.Equal(bazCache, bazCache2);
1090+
Assert.Equal(bazCache, bazCache3);
10861091

10871092
Assert.NotNull(quxCache);
10881093
Assert.Equal(quxCacheOriginal, quxCache);
10891094
Assert.Equal(quxCache, quxCache2);
10901095
}
10911096

10921097
[Fact]
1093-
public void CanConsumeKeyedServices()
1098+
public void CanUseKeyedLogger()
10941099
{
10951100
var services = new ServiceCollection();
10961101

10971102
// NOTE: THIS SHOULD BE TRANSIENT, NOT SINGLETON: I'M DOING THIS ONLY FOR TESTING PURPOSES
10981103
var registeredLogger = new ListLogger<FusionCache>();
10991104
services.AddKeyedSingleton<ILogger<FusionCache>>("FooLogger", registeredLogger);
11001105

1106+
services.AddFusionCache()
1107+
.TryWithRegisteredKeyedLogger("FooLogger");
1108+
1109+
using var serviceProvider = services.BuildServiceProvider();
1110+
1111+
var cache = serviceProvider.GetRequiredService<IFusionCache>();
1112+
1113+
var logger = GetLogger(cache);
1114+
1115+
Assert.NotNull(cache);
1116+
1117+
Assert.NotNull(logger);
1118+
Assert.Equal(registeredLogger, logger);
1119+
}
1120+
1121+
[Fact]
1122+
public void CanUseKeyedMemoryCache()
1123+
{
1124+
var services = new ServiceCollection();
1125+
11011126
var registeredMemoryCache = new ChaosMemoryCache(new MemoryCache(new MemoryCacheOptions()));
11021127
services.AddKeyedSingleton<IMemoryCache>("FooMemoryCache", registeredMemoryCache);
11031128

1129+
services.AddFusionCache()
1130+
.TryWithRegisteredKeyedMemoryCache("FooMemoryCache");
1131+
1132+
using var serviceProvider = services.BuildServiceProvider();
1133+
1134+
var cache = serviceProvider.GetRequiredService<IFusionCache>();
1135+
1136+
var memoryCache = GetMemoryCache(cache);
1137+
1138+
Assert.NotNull(cache);
1139+
1140+
Assert.NotNull(memoryCache);
1141+
Assert.Equal(registeredMemoryCache, memoryCache);
1142+
}
1143+
1144+
[Fact]
1145+
public void CanUseKeyedDistributedCache()
1146+
{
1147+
var services = new ServiceCollection();
1148+
11041149
// NOTE: THIS SHOULD BE TRANSIENT, NOT SINGLETON: I'M DOING THIS ONLY FOR TESTING PURPOSES
11051150
var registeredSerializer = new ChaosSerializer(new FusionCacheSystemTextJsonSerializer());
11061151
services.AddKeyedSingleton<IFusionCacheSerializer>("FooSerializer", registeredSerializer);
11071152

11081153
var registeredDistributedCache = new ChaosDistributedCache(new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions())));
11091154
services.AddKeyedSingleton<IDistributedCache>("FooDistributedCache", registeredDistributedCache);
11101155

1156+
services.AddFusionCache()
1157+
.WithRegisteredKeyedSerializer("FooSerializer")
1158+
.TryWithRegisteredKeyedDistributedCache("FooDistributedCache");
1159+
1160+
using var serviceProvider = services.BuildServiceProvider();
1161+
1162+
var cache = serviceProvider.GetRequiredService<IFusionCache>();
1163+
1164+
var serializer = GetSerializer(cache);
1165+
var distributedCache = GetDistributedCache<IDistributedCache>(cache);
1166+
1167+
Assert.NotNull(cache);
1168+
1169+
Assert.NotNull(serializer);
1170+
Assert.Equal(registeredSerializer, serializer);
1171+
}
1172+
1173+
[Fact]
1174+
public void CanUseKeyedMemoryLocker()
1175+
{
1176+
var services = new ServiceCollection();
1177+
11111178
// NOTE: THIS SHOULD BE TRANSIENT, NOT SINGLETON: I'M DOING THIS ONLY FOR TESTING PURPOSES
11121179
var registeredMemoryLocker = new ChaosMemoryLocker(new StandardMemoryLocker());
11131180
services.AddKeyedSingleton<IFusionCacheMemoryLocker>("FooMemoryLocker", registeredMemoryLocker);
11141181

1182+
services.AddFusionCache()
1183+
.TryWithRegisteredKeyedMemoryLocker("FooMemoryLocker");
1184+
1185+
using var serviceProvider = services.BuildServiceProvider();
1186+
1187+
var cache = serviceProvider.GetRequiredService<IFusionCache>();
1188+
1189+
var memoryLocker = GetMemoryLocker(cache);
1190+
1191+
Assert.NotNull(cache);
1192+
1193+
Assert.NotNull(memoryLocker);
1194+
Assert.Equal(registeredMemoryLocker, memoryLocker);
1195+
}
1196+
1197+
[Fact]
1198+
public void CanUseKeyedBackplane()
1199+
{
1200+
var services = new ServiceCollection();
1201+
11151202
// NOTE: THIS SHOULD BE TRANSIENT, NOT SINGLETON: I'M DOING THIS ONLY FOR TESTING PURPOSES
11161203
var registeredBackplane = new ChaosBackplane(new MemoryBackplane(new MemoryBackplaneOptions()));
11171204
services.AddKeyedSingleton<IFusionCacheBackplane>("FooBackplane", registeredBackplane);
11181205

1206+
services.AddFusionCache()
1207+
.TryWithRegisteredKeyedBackplane("FooBackplane");
1208+
1209+
using var serviceProvider = services.BuildServiceProvider();
1210+
1211+
var cache = serviceProvider.GetRequiredService<IFusionCache>();
1212+
1213+
var backplane = GetBackplane<IFusionCacheBackplane>(cache);
1214+
1215+
Assert.NotNull(cache);
1216+
1217+
Assert.NotNull(backplane);
1218+
Assert.Equal(registeredBackplane, backplane);
1219+
}
1220+
1221+
[Fact]
1222+
public void CanUseKeyedPlugins()
1223+
{
1224+
var services = new ServiceCollection();
1225+
11191226
// NOTE: THIS SHOULD BE TRANSIENT, NOT SINGLETON: I'M DOING THIS ONLY FOR TESTING PURPOSES
11201227
IFusionCachePlugin[] registeredKeyedPlugins = [
11211228
new SimplePlugin("KP1"),
@@ -1137,12 +1244,83 @@ public void CanConsumeKeyedServices()
11371244
}
11381245

11391246
services.AddFusionCache()
1140-
.WithRegisteredKeyedLogger("FooLogger")
1141-
.WithRegisteredKeyedMemoryCache("FooMemoryCache")
1142-
.WithRegisteredKeyedSerializer("FooSerializer")
1143-
.WithRegisteredKeyedDistributedCache("FooDistributedCache")
1144-
.WithRegisteredKeyedMemoryLocker("FooMemoryLocker")
1145-
.WithRegisteredKeyedBackplane("FooBackplane")
1247+
.WithAllRegisteredPlugins()
1248+
.WithAllRegisteredKeyedPlugins("FooPlugins");
1249+
1250+
using var serviceProvider = services.BuildServiceProvider();
1251+
1252+
var cache = serviceProvider.GetRequiredService<IFusionCache>();
1253+
1254+
var plugins = GetPlugins(cache);
1255+
1256+
Assert.NotNull(cache);
1257+
1258+
foreach (var plugin in registeredKeyedPlugins)
1259+
{
1260+
Assert.Contains(plugin, plugins!);
1261+
}
1262+
1263+
foreach (var plugin in registeredNonKeyedPlugins)
1264+
{
1265+
Assert.Contains(plugin, plugins!);
1266+
}
1267+
Assert.Equal(registeredKeyedPlugins.Length + registeredNonKeyedPlugins.Length, plugins!.Count());
1268+
}
1269+
1270+
[Fact]
1271+
public void CanUseKeyedServices()
1272+
{
1273+
var services = new ServiceCollection();
1274+
1275+
// NOTE: THIS SHOULD BE TRANSIENT, NOT SINGLETON: I'M DOING THIS ONLY FOR TESTING PURPOSES
1276+
var registeredLogger = new ListLogger<FusionCache>();
1277+
services.AddKeyedSingleton<ILogger<FusionCache>>("FooLogger", registeredLogger);
1278+
1279+
var registeredMemoryCache = new ChaosMemoryCache(new MemoryCache(new MemoryCacheOptions()));
1280+
services.AddKeyedSingleton<IMemoryCache>("FooMemoryCache", registeredMemoryCache);
1281+
1282+
// NOTE: THIS SHOULD BE TRANSIENT, NOT SINGLETON: I'M DOING THIS ONLY FOR TESTING PURPOSES
1283+
var registeredSerializer = new ChaosSerializer(new FusionCacheSystemTextJsonSerializer());
1284+
services.AddKeyedSingleton<IFusionCacheSerializer>("FooSerializer", registeredSerializer);
1285+
1286+
var registeredDistributedCache = new ChaosDistributedCache(new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions())));
1287+
services.AddKeyedSingleton<IDistributedCache>("FooDistributedCache", registeredDistributedCache);
1288+
1289+
// NOTE: THIS SHOULD BE TRANSIENT, NOT SINGLETON: I'M DOING THIS ONLY FOR TESTING PURPOSES
1290+
var registeredMemoryLocker = new ChaosMemoryLocker(new StandardMemoryLocker());
1291+
services.AddKeyedSingleton<IFusionCacheMemoryLocker>("FooMemoryLocker", registeredMemoryLocker);
1292+
1293+
// NOTE: THIS SHOULD BE TRANSIENT, NOT SINGLETON: I'M DOING THIS ONLY FOR TESTING PURPOSES
1294+
var registeredBackplane = new ChaosBackplane(new MemoryBackplane(new MemoryBackplaneOptions()));
1295+
services.AddKeyedSingleton<IFusionCacheBackplane>("FooBackplane", registeredBackplane);
1296+
1297+
// NOTE: THIS SHOULD BE TRANSIENT, NOT SINGLETON: I'M DOING THIS ONLY FOR TESTING PURPOSES
1298+
IFusionCachePlugin[] registeredKeyedPlugins = [
1299+
new SimplePlugin("KP1"),
1300+
new SimplePlugin("KP2"),
1301+
new SimplePlugin("KP3")
1302+
];
1303+
foreach (var plugin in registeredKeyedPlugins)
1304+
{
1305+
services.AddKeyedSingleton<IFusionCachePlugin>("FooPlugins", plugin);
1306+
}
1307+
IFusionCachePlugin[] registeredNonKeyedPlugins = [
1308+
new SimplePlugin("NKP1"),
1309+
new SimplePlugin("NKP2"),
1310+
new SimplePlugin("NKP3")
1311+
];
1312+
foreach (var plugin in registeredNonKeyedPlugins)
1313+
{
1314+
services.AddSingleton<IFusionCachePlugin>(plugin);
1315+
}
1316+
1317+
services.AddFusionCache()
1318+
.TryWithRegisteredKeyedLogger("FooLogger")
1319+
.TryWithRegisteredKeyedMemoryCache("FooMemoryCache")
1320+
.TryWithRegisteredKeyedSerializer("FooSerializer")
1321+
.TryWithRegisteredKeyedDistributedCache("FooDistributedCache")
1322+
.TryWithRegisteredKeyedMemoryLocker("FooMemoryLocker")
1323+
.TryWithRegisteredKeyedBackplane("FooBackplane")
11461324
.WithAllRegisteredPlugins()
11471325
.WithAllRegisteredKeyedPlugins("FooPlugins");
11481326

@@ -1187,6 +1365,7 @@ public void CanConsumeKeyedServices()
11871365
{
11881366
Assert.Contains(plugin, plugins!);
11891367
}
1368+
Assert.Equal(registeredKeyedPlugins.Length + registeredNonKeyedPlugins.Length, plugins!.Count());
11901369
}
11911370

11921371
[Fact]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"v":"Sloths are cool!","m":{"e":"2033-07-08T14:53:13.4520833+00:00","f":true,"ea":"2033-06-28T14:53:13.4520833+00:00","et":"MyETagValue","lm":"2033-03-30T14:53:13.4520833+00:00"},"t":638528613274343519}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
Sloths are cool!-��Ψ�ɭ���������" MyETagValue(����Ϋ�߰���̠�
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"v":"Sloths are cool!","m":{"e":"2033-07-08T14:53:13.4520833+00:00","f":true,"ea":"2033-06-28T14:53:13.4520833+00:00","et":"MyETagValue","lm":"2033-03-30T14:53:13.4520833+00:00"},"t":638528613274343519}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"Value":"Sloths are cool!","Metadata":{"LogicalExpiration":"2033-07-08T14:53:13.4520833+00:00","IsFromFailSafe":true,"EagerExpiration":"2033-06-28T14:53:13.4520833+00:00","ETag":"MyETagValue","LastModified":"2033-03-30T14:53:13.4520833+00:00"},"Timestamp":638528613274343519}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
namespace FusionCacheTests.Stuff
2+
{
3+
public record SimpleServiceKey(int value);
4+
}

‎tests/ZiggyCreatures.FusionCache.Tests/ZiggyCreatures.FusionCache.Tests.csproj

+339
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,57 @@
1212
</Content>
1313
</ItemGroup>
1414

15+
<ItemGroup>
16+
<None Remove="Samples\fusioncachecysharpmemorypackserializer__v0_20_0_0.bin" />
17+
<None Remove="Samples\fusioncachecysharpmemorypackserializer__v0_21_0_0.bin" />
18+
<None Remove="Samples\fusioncachecysharpmemorypackserializer__v0_22_0_0.bin" />
19+
<None Remove="Samples\fusioncachecysharpmemorypackserializer__v0_23_0_0.bin" />
20+
<None Remove="Samples\fusioncachecysharpmemorypackserializer__v0_24_0_0.bin" />
21+
<None Remove="Samples\fusioncachecysharpmemorypackserializer__v0_25_0_0.bin" />
22+
<None Remove="Samples\fusioncachecysharpmemorypackserializer__v0_26_0_0.bin" />
23+
<None Remove="Samples\fusioncachecysharpmemorypackserializer__v1_1_0_0.bin" />
24+
<None Remove="Samples\fusioncacheneueccmessagepackserializer__v0_20_0_0.bin" />
25+
<None Remove="Samples\fusioncacheneueccmessagepackserializer__v0_21_0_0.bin" />
26+
<None Remove="Samples\fusioncacheneueccmessagepackserializer__v0_22_0_0.bin" />
27+
<None Remove="Samples\fusioncacheneueccmessagepackserializer__v0_23_0_0.bin" />
28+
<None Remove="Samples\fusioncacheneueccmessagepackserializer__v0_24_0_0.bin" />
29+
<None Remove="Samples\fusioncacheneueccmessagepackserializer__v0_25_0_0.bin" />
30+
<None Remove="Samples\fusioncacheneueccmessagepackserializer__v0_26_0_0.bin" />
31+
<None Remove="Samples\fusioncacheneueccmessagepackserializer__v1_1_0_0.bin" />
32+
<None Remove="Samples\fusioncachenewtonsoftjsonserializer__v0_20_0_0.bin" />
33+
<None Remove="Samples\fusioncachenewtonsoftjsonserializer__v0_21_0_0.bin" />
34+
<None Remove="Samples\fusioncachenewtonsoftjsonserializer__v0_22_0_0.bin" />
35+
<None Remove="Samples\fusioncachenewtonsoftjsonserializer__v0_23_0_0.bin" />
36+
<None Remove="Samples\fusioncachenewtonsoftjsonserializer__v0_24_0_0.bin" />
37+
<None Remove="Samples\fusioncachenewtonsoftjsonserializer__v0_25_0_0.bin" />
38+
<None Remove="Samples\fusioncachenewtonsoftjsonserializer__v0_26_0_0.bin" />
39+
<None Remove="Samples\fusioncachenewtonsoftjsonserializer__v1_1_0_0.bin" />
40+
<None Remove="Samples\fusioncacheprotobufnetserializer__v0_20_0_0.bin" />
41+
<None Remove="Samples\fusioncacheprotobufnetserializer__v0_21_0_0.bin" />
42+
<None Remove="Samples\fusioncacheprotobufnetserializer__v0_22_0_0.bin" />
43+
<None Remove="Samples\fusioncacheprotobufnetserializer__v0_23_0_0.bin" />
44+
<None Remove="Samples\fusioncacheprotobufnetserializer__v0_24_0_0.bin" />
45+
<None Remove="Samples\fusioncacheprotobufnetserializer__v0_25_0_0.bin" />
46+
<None Remove="Samples\fusioncacheprotobufnetserializer__v0_26_0_0.bin" />
47+
<None Remove="Samples\fusioncacheprotobufnetserializer__v1_1_0_0.bin" />
48+
<None Remove="Samples\fusioncacheservicestackjsonserializer__v0_20_0_0.bin" />
49+
<None Remove="Samples\fusioncacheservicestackjsonserializer__v0_21_0_0.bin" />
50+
<None Remove="Samples\fusioncacheservicestackjsonserializer__v0_22_0_0.bin" />
51+
<None Remove="Samples\fusioncacheservicestackjsonserializer__v0_23_0_0.bin" />
52+
<None Remove="Samples\fusioncacheservicestackjsonserializer__v0_24_0_0.bin" />
53+
<None Remove="Samples\fusioncacheservicestackjsonserializer__v0_25_0_0.bin" />
54+
<None Remove="Samples\fusioncacheservicestackjsonserializer__v0_26_0_0.bin" />
55+
<None Remove="Samples\fusioncacheservicestackjsonserializer__v1_1_0_0.bin" />
56+
<None Remove="Samples\fusioncachesystemtextjsonserializer__v0_20_0_0.bin" />
57+
<None Remove="Samples\fusioncachesystemtextjsonserializer__v0_21_0_0.bin" />
58+
<None Remove="Samples\fusioncachesystemtextjsonserializer__v0_22_0_0.bin" />
59+
<None Remove="Samples\fusioncachesystemtextjsonserializer__v0_23_0_0.bin" />
60+
<None Remove="Samples\fusioncachesystemtextjsonserializer__v0_24_0_0.bin" />
61+
<None Remove="Samples\fusioncachesystemtextjsonserializer__v0_25_0_0.bin" />
62+
<None Remove="Samples\fusioncachesystemtextjsonserializer__v0_26_0_0.bin" />
63+
<None Remove="Samples\fusioncachesystemtextjsonserializer__v1_1_0_0.bin" />
64+
</ItemGroup>
65+
1566
<ItemGroup>
1667
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.2" />
1768
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
@@ -44,4 +95,292 @@
4495
<ProjectReference Include="..\..\src\ZiggyCreatures.FusionCache\ZiggyCreatures.FusionCache.csproj" />
4596
</ItemGroup>
4697

98+
<ItemGroup>
99+
<Content Update="Samples\fusioncachecysharpmemorypackserializer__v0_20_0_0.bin">
100+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
101+
</Content>
102+
</ItemGroup>
103+
104+
<ItemGroup>
105+
<Content Update="Samples\fusioncachecysharpmemorypackserializer__v0_21_0_0.bin">
106+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
107+
</Content>
108+
</ItemGroup>
109+
110+
<ItemGroup>
111+
<Content Update="Samples\fusioncachecysharpmemorypackserializer__v0_22_0_0.bin">
112+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
113+
</Content>
114+
</ItemGroup>
115+
116+
<ItemGroup>
117+
<Content Update="Samples\fusioncachecysharpmemorypackserializer__v0_23_0_0.bin">
118+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
119+
</Content>
120+
</ItemGroup>
121+
122+
<ItemGroup>
123+
<Content Update="Samples\fusioncachecysharpmemorypackserializer__v0_24_0_0.bin">
124+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
125+
</Content>
126+
</ItemGroup>
127+
128+
<ItemGroup>
129+
<Content Update="Samples\fusioncachecysharpmemorypackserializer__v0_25_0_0.bin">
130+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
131+
</Content>
132+
</ItemGroup>
133+
134+
<ItemGroup>
135+
<Content Update="Samples\fusioncachecysharpmemorypackserializer__v0_26_0_0.bin">
136+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
137+
</Content>
138+
</ItemGroup>
139+
140+
<ItemGroup>
141+
<Content Update="Samples\fusioncacheneueccmessagepackserializer__v0_20_0_0.bin">
142+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
143+
</Content>
144+
</ItemGroup>
145+
146+
<ItemGroup>
147+
<Content Update="Samples\fusioncacheneueccmessagepackserializer__v0_21_0_0.bin">
148+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
149+
</Content>
150+
</ItemGroup>
151+
152+
<ItemGroup>
153+
<Content Update="Samples\fusioncacheneueccmessagepackserializer__v0_22_0_0.bin">
154+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
155+
</Content>
156+
</ItemGroup>
157+
158+
<ItemGroup>
159+
<Content Update="Samples\fusioncacheneueccmessagepackserializer__v0_23_0_0.bin">
160+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
161+
</Content>
162+
</ItemGroup>
163+
164+
<ItemGroup>
165+
<Content Update="Samples\fusioncacheneueccmessagepackserializer__v0_24_0_0.bin">
166+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
167+
</Content>
168+
</ItemGroup>
169+
170+
<ItemGroup>
171+
<Content Update="Samples\fusioncacheneueccmessagepackserializer__v0_25_0_0.bin">
172+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
173+
</Content>
174+
</ItemGroup>
175+
176+
<ItemGroup>
177+
<Content Update="Samples\fusioncacheneueccmessagepackserializer__v0_26_0_0.bin">
178+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
179+
</Content>
180+
</ItemGroup>
181+
182+
<ItemGroup>
183+
<Content Update="Samples\fusioncachenewtonsoftjsonserializer__v0_20_0_0.bin">
184+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
185+
</Content>
186+
</ItemGroup>
187+
188+
<ItemGroup>
189+
<Content Update="Samples\fusioncachenewtonsoftjsonserializer__v0_21_0_0.bin">
190+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
191+
</Content>
192+
</ItemGroup>
193+
194+
<ItemGroup>
195+
<Content Update="Samples\fusioncachenewtonsoftjsonserializer__v0_22_0_0.bin">
196+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
197+
</Content>
198+
</ItemGroup>
199+
200+
<ItemGroup>
201+
<Content Update="Samples\fusioncachenewtonsoftjsonserializer__v0_23_0_0.bin">
202+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
203+
</Content>
204+
</ItemGroup>
205+
206+
<ItemGroup>
207+
<Content Update="Samples\fusioncachenewtonsoftjsonserializer__v0_24_0_0.bin">
208+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
209+
</Content>
210+
</ItemGroup>
211+
212+
<ItemGroup>
213+
<Content Update="Samples\fusioncachenewtonsoftjsonserializer__v0_25_0_0.bin">
214+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
215+
</Content>
216+
</ItemGroup>
217+
218+
<ItemGroup>
219+
<Content Update="Samples\fusioncachenewtonsoftjsonserializer__v0_26_0_0.bin">
220+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
221+
</Content>
222+
</ItemGroup>
223+
224+
<ItemGroup>
225+
<Content Update="Samples\fusioncacheprotobufnetserializer__v0_20_0_0.bin">
226+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
227+
</Content>
228+
</ItemGroup>
229+
230+
<ItemGroup>
231+
<Content Update="Samples\fusioncacheprotobufnetserializer__v0_21_0_0.bin">
232+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
233+
</Content>
234+
</ItemGroup>
235+
236+
<ItemGroup>
237+
<Content Update="Samples\fusioncacheprotobufnetserializer__v0_22_0_0.bin">
238+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
239+
</Content>
240+
</ItemGroup>
241+
242+
<ItemGroup>
243+
<Content Update="Samples\fusioncacheprotobufnetserializer__v0_23_0_0.bin">
244+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
245+
</Content>
246+
</ItemGroup>
247+
248+
<ItemGroup>
249+
<Content Update="Samples\fusioncacheprotobufnetserializer__v0_24_0_0.bin">
250+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
251+
</Content>
252+
</ItemGroup>
253+
254+
<ItemGroup>
255+
<Content Update="Samples\fusioncacheprotobufnetserializer__v0_25_0_0.bin">
256+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
257+
</Content>
258+
</ItemGroup>
259+
260+
<ItemGroup>
261+
<Content Update="Samples\fusioncacheprotobufnetserializer__v0_26_0_0.bin">
262+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
263+
</Content>
264+
</ItemGroup>
265+
266+
<ItemGroup>
267+
<Content Update="Samples\fusioncacheservicestackjsonserializer__v0_20_0_0.bin">
268+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
269+
</Content>
270+
</ItemGroup>
271+
272+
<ItemGroup>
273+
<Content Update="Samples\fusioncacheservicestackjsonserializer__v0_21_0_0.bin">
274+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
275+
</Content>
276+
</ItemGroup>
277+
278+
<ItemGroup>
279+
<Content Update="Samples\fusioncacheservicestackjsonserializer__v0_22_0_0.bin">
280+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
281+
</Content>
282+
</ItemGroup>
283+
284+
<ItemGroup>
285+
<Content Update="Samples\fusioncacheservicestackjsonserializer__v0_23_0_0.bin">
286+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
287+
</Content>
288+
</ItemGroup>
289+
290+
<ItemGroup>
291+
<Content Update="Samples\fusioncacheservicestackjsonserializer__v0_24_0_0.bin">
292+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
293+
</Content>
294+
</ItemGroup>
295+
296+
<ItemGroup>
297+
<Content Update="Samples\fusioncacheservicestackjsonserializer__v0_25_0_0.bin">
298+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
299+
</Content>
300+
</ItemGroup>
301+
302+
<ItemGroup>
303+
<Content Update="Samples\fusioncacheservicestackjsonserializer__v0_26_0_0.bin">
304+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
305+
</Content>
306+
</ItemGroup>
307+
308+
<ItemGroup>
309+
<Content Update="Samples\fusioncachesystemtextjsonserializer__v0_20_0_0.bin">
310+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
311+
</Content>
312+
</ItemGroup>
313+
314+
<ItemGroup>
315+
<Content Update="Samples\fusioncachesystemtextjsonserializer__v0_21_0_0.bin">
316+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
317+
</Content>
318+
</ItemGroup>
319+
320+
<ItemGroup>
321+
<Content Update="Samples\fusioncachesystemtextjsonserializer__v0_22_0_0.bin">
322+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
323+
</Content>
324+
</ItemGroup>
325+
326+
<ItemGroup>
327+
<Content Update="Samples\fusioncachesystemtextjsonserializer__v0_23_0_0.bin">
328+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
329+
</Content>
330+
</ItemGroup>
331+
332+
<ItemGroup>
333+
<Content Update="Samples\fusioncachesystemtextjsonserializer__v0_24_0_0.bin">
334+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
335+
</Content>
336+
</ItemGroup>
337+
338+
<ItemGroup>
339+
<Content Update="Samples\fusioncachesystemtextjsonserializer__v0_25_0_0.bin">
340+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
341+
</Content>
342+
</ItemGroup>
343+
344+
<ItemGroup>
345+
<Content Update="Samples\fusioncachesystemtextjsonserializer__v0_26_0_0.bin">
346+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
347+
</Content>
348+
</ItemGroup>
349+
350+
<ItemGroup>
351+
<Content Update="Samples\fusioncachecysharpmemorypackserializer__v1_1_0_0.bin">
352+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
353+
</Content>
354+
</ItemGroup>
355+
356+
<ItemGroup>
357+
<Content Update="Samples\fusioncacheneueccmessagepackserializer__v1_1_0_0.bin">
358+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
359+
</Content>
360+
</ItemGroup>
361+
362+
<ItemGroup>
363+
<Content Update="Samples\fusioncachenewtonsoftjsonserializer__v1_1_0_0.bin">
364+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
365+
</Content>
366+
</ItemGroup>
367+
368+
<ItemGroup>
369+
<Content Update="Samples\fusioncacheprotobufnetserializer__v1_1_0_0.bin">
370+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
371+
</Content>
372+
</ItemGroup>
373+
374+
<ItemGroup>
375+
<Content Update="Samples\fusioncacheservicestackjsonserializer__v1_1_0_0.bin">
376+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
377+
</Content>
378+
</ItemGroup>
379+
380+
<ItemGroup>
381+
<Content Update="Samples\fusioncachesystemtextjsonserializer__v1_1_0_0.bin">
382+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
383+
</Content>
384+
</ItemGroup>
385+
47386
</Project>

0 commit comments

Comments
 (0)
Please sign in to comment.