Closed AdrianoAE closed 1 year ago
This same exception occurs when using records without parameterless constructors. Refactoring the UrlDetails
object from the Orleans quickstart to a record with a primary constructor fails
[GenerateSerializer]
public record class UrlDetails([property: Id(0)] string FullUrl, [property: Id(1)] string ShortenedRouteSegment);
Causes
Orleans.Runtime.OrleansException: Error from storage provider MemoryGrainStorage.url during ReadStateAsync for grain urlshortener/39B5C80
Exc level 0: System.MissingMethodException: Cannot dynamically create an instance of type 'UrlDetails'. Reason: No parameterless constructor defined.
at System.RuntimeType.ActivatorCache..ctor(RuntimeType rt)
at System.RuntimeType.CreateInstanceOfT()
at System.Activator.CreateInstance[T]()
at Orleans.Core.StateStorageBridge`1.get_GrainState() in /_/src/Orleans.Runtime/Storage/StateStorageBridge.cs:line 42
at Orleans.Core.StateStorageBridge`1.ReadStateAsync() in /_/src/Orleans.Runtime/Storage/StateStorageBridge.cs:line 72
---> System.MissingMethodException: Cannot dynamically create an instance of type 'UrlDetails'. Reason: No parameterless constructor defined.
at System.RuntimeType.ActivatorCache..ctor(RuntimeType rt)
at System.RuntimeType.CreateInstanceOfT()
at System.Activator.CreateInstance[T]()
at Orleans.Core.StateStorageBridge`1.get_GrainState() in /_/src/Orleans.Runtime/Storage/StateStorageBridge.cs:line 42
at Orleans.Core.StateStorageBridge`1.ReadStateAsync() in /_/src/Orleans.Runtime/Storage/StateStorageBridge.cs:line 72
--- End of inner exception stack trace ---
at Orleans.Core.StateStorageBridge`1.OnError(Exception exception, ErrorCode id, String operation) in /_/src/Orleans.Runtime/Storage/StateStorageBridge.cs:line 168
at Orleans.Core.StateStorageBridge`1.ReadStateAsync() in /_/src/Orleans.Runtime/Storage/StateStorageBridge.cs:line 78
at Orleans.LifecycleSubject.OnStart(CancellationToken cancellationToken) in /_/src/Orleans.Core/Lifecycle/LifecycleSubject.cs:line 118
at Orleans.Internal.OrleansTaskExtentions.WithCancellation(Task taskToComplete, String message, CancellationToken cancellationToken) in /_/src/Orleans.Core/Async/TaskExtensions.cs:line 145
at Orleans.Runtime.ActivationData.<ActivateAsync>g__CallActivateAsync|139_0(Dictionary`2 requestContextData, CancellationToken cancellationToken) in /_/src/Orleans.Runtime/Catalog/ActivationData.cs:line 1400
at Orleans.Serialization.Invocation.ResponseCompletionSource.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token) in /_/src/Orleans.Serialization/Invocation/ResponseCompletionSource.cs:line 98
at System.Threading.Tasks.ValueTask.ValueTaskSourceAsTask.<>c.<.cctor>b__4_0(Object state)
--- End of stack trace from previous location ---
at Program.<>c.<<Main>b__0_2>d.MoveNext() in C:\path\Program.cs:line 41
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Http.RequestDelegateFactory.ExecuteTaskResult[T](Task`1 task, HttpContext httpContext)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
This seems to contradict the documentation that serializing record
types is supported.
PR updated with a unit test for that
When using IPersistentState the type instantiation is currently using
Activator.CreateInstance
to activate the state type, as such unserializable types like classes without public constructors are not possible to be instantiated and an exception is thrown