Request: Provide workarounds for caching unserializable types
When writing LINQPad scripts, these days I exclusively use records and immutable types for my data structures. Occasionally I need to cache the results as I work on an implementation so I'm not doing constantly making expensive queries as I test it. The only requirement is that all types to be cached must be marked as serializable.
void Main() { var list = Util.Cache(() => new Record(ImmutableList.Create("foo", "Bar"))); DumpIt(list); } [Serializable] record Record(ImmutableList<string> Items); void DumpIt<T>(T obj, [CallerArgumentExpression(nameof(obj))] string? expr = default) { obj.Dump(expr); }
SerializationException: Don't know how to serialize System.Collections.Immutable.ImmutableList`1[[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]] at LINQPad.Util.Cache[T](Func`1 dataFetcher, String key, Boolean& fromCache) at LINQPad.Util.Cache[T](Func`1 dataFetcher, String key) at LINQPad.Util.Cache[T](Func`1 dataFetcher) at UserQuery.Main(), line 3
https://share.linqpad.net/83mv2om3.linq
The types in System.Collections.Immutable
do not mark them serializable so they cannot be cached by linqpad. To work around this, I try to cache the string representations. However this approach is not always feasible without writing a lot of code, especially when working with third party libraries.
Can other mechanisms be added to allow for caching unserializable types?
Maybe a way to register a serialize/deserialize function/interface that would handle the conversions to serializable forms. Maybe fallback to JSON for simple types and include implementations for more commonly used types?
Comments
Something like this and this and implicit
ImmutableList<T>
conversion operator?LINQPad's inbuilt serialization supports arrays and ordinary lists, so the following will work:
Personally, I use arrays for read-only collections when scripting because it's less noisy.
Supporting immutable collections is tricky because they lack ordinary constructors. Would probably end up having to code each one separately, taking care to ensuring that it doesn't break anything with scripts that target any of the older .NET versions that LINQPad supports.