Cannot initialize MemoryPack with UseDisk
Simple reproduction. Create new console project, add following nugets.
- EasyCaching.Disk 1.9.0
- EasyCaching.Serialization.MemoryPack 1.9.0
- .NET 7
Copy & paste the following code and run.
// See https://aka.ms/new-console-template for more information
using EasyCaching.Core;
using EasyCaching.Disk;
using EasyCaching.Serialization.MemoryPack;
using MemoryPack;
using Microsoft.Extensions.DependencyInjection;
var sc = new ServiceCollection();
sc.AddEasyCaching(o =>
{
o.UseDisk(config =>
{
config.SerializerName = "mempack";
config.DBConfig = new DiskDbOptions { BasePath = Path.GetTempPath() };
}).WithMemoryPack();
});
ServiceProvider sp = sc.BuildServiceProvider();
IEasyCachingProvider provider = sp.GetRequiredService<IEasyCachingProvider>();
provider.Set("CACHE_KEY", new Test(), TimeSpan.FromDays(1));
Console.ReadLine();
[MemoryPackable]
public partial class Test
{
public string Name { get; set; } = "asdf";
}
Expected behavior: No exception is thrown, Test class value is cached on disk with CACHE_KEY in MemoryPack format.
Actual behavior:
System.MissingMethodException: 'Method not found: 'Void MemoryPack.MemoryPackSerializerOptions.set_StringEncoding(MemoryPack.StringEncoding)'.'
Call stack
at EasyCaching.Serialization.Json.MemoryPackOptionsExtension.<AddServices>b__3_1(IServiceProvider x)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetServices[T](IServiceProvider provider)
at EasyCaching.Disk.DiskOptionsExtension.<AddServices>b__3_0(IServiceProvider x)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Program.<Main>$(String[] args) in C:\Users\lesar\Source\Repos\Locura\src\ConsoleTest\Program.cs:line 20
Also, I was little surprised by the first line in the call stack
at EasyCaching.Serialization.Json.MemoryPackOptionsExtension.<AddServices>b__3_1(IServiceProvider x)
...because MemoryPack is binary serialization, not JSON.
So I looked here to see that indeed MemoryPackOptionsExtension is indeed in the EasyCaching.Serialization.Json namespace.
So I tried copying the source code of MemoryPack serializer and another issue showed up, apparently UseDisk cannot really be used with WithMemoryPack because the serialized value is not the serialized class but EasyCaching.Disk.DiskCacheValue so I cannot add the [MemoryPackable] attribute to it.
MemoryPack uses source generators so you cannot specify the serialization in runtime. This means that UseDisk must either support MemoryPack explicitly by specifying a different DiskCacheValue type or the DiskCacheValue must be serialized/deserialized using a different serializer.