Open Professional-amateur-dev opened 1 year ago
I have found the same issue. I believe it stems from the fact that the code generation seems to only run on the assembly being compiled, and on dependencies explicitly linked for code generation to run on:
https://github.com/dotnet/orleans/blob/v7.1.0/src/Orleans.CodeGenerator/CodeGenerator.cs#L428
When determining which assemblies to examine (and hence to run code generation on), this starts at the compiling assembly, and the recursively looks at other assemblies that have been linked with the GenerateCodeForDeclaringAssemblyAttribute
.
So in my case where I have types in another project in my solution, I was able to add
[assembly: GenerateCodeForDeclaringAssembly(typeof(SomeTypeInMyOtherAssembly))]
in my project, instruct the code generation to also generate serializers for types in that other assembly. I believe this should work in the same way for NuGet packages.
This isn't great in our case though. We have a library that sits on top of Orleans, and it means that consumers of that library have to instruct Orleans explicitly to run code generation on the library, rather than just using it and having it work automatically. I haven't yet found another way around that.
Thanks for the code snippet, the error is now gone.
I now have another error:
Could not find a codec for type System.Text.Json.JsonElement.
The error is for all System.Objects I have in the project, example object:
[Id(0), Immutable] [JsonPropertyName("ext")] [DataMember(Name ="ext")] public object ObjectExtraInfo { get; set; }
Similar thing is happening with Interfaces, like in my example class in the question, which has a IRequest Interface. For now I've replaced the interface and object with a class and it works (in this specific class), but that's not a real solution.
I need to have serializable Interfaces and System.Object since I have another ~1000 classes and they are used everywhere. Interfaces are required because we have a generic IRequest interface that is shared between multiple project, and now I have to always Map it to a Internal class and then map it again when I'm sending it to other services. Objects are required because we don't always know what we will receive in that object, so it need to stay as System.Object.
Furthermore, you should add support to import all classes with GeneratedCodeAttribute in a specific assembly. Currently we need to manually add all the classes with that attribute, which is time consuming and unnecessary.
Triage: we could consider providing codecs out of the box for JsonElement and the like.
As a workaround for now you could try serializing/deserializing your JSON data as strings.
Just hit this. Looks like a huge problem for anyone using class libraries. Aborting our attempt to move from Orleans 3.x to Orleans 7. More evidence 7 is not ready for primetime.
@yoDon I believe this is by design and there's nothing to fix or improve here except as noted above, we may include codecs for System.Text.Json & Newtonsoft internal types in case they are being sent directly over the wire.
Orleans 7 moves away from the automatic (i.e. magic) serialization approach and requires you to annotate classes & members explicitly. The auto approach was fragile to changes in your data model, often putting you in an unrecoverable situation, eg if you added or removed a field from a type. You can use JSON, Protocol Buffers, or another serialization library instead, if you prefer: https://learn.microsoft.com/en-us/dotnet/orleans/host/configuration-guide/serialization-configuration?pivots=orleans-7-0
There is no issue with serializing types from libraries.
If there's something we can help you with, please let us know. I am less available this week because I am on vacation, but I'll try to respond regardless
@ReubenBond thanks for clarifying that the behavior @Professional-amateur-dev and @david-obee mentioned here is expected/by-design. Given that GenerateCodeForDeclaringAssembly
doesn't seem to be documented anywhere, I hope it's ok I've created a couple separate more granular issues to capture this documentation issue and a couple other not-obvious-to-me issues I encountered while porting a non-trivial Orleans 3.x project to Orleans 7.
I'm a huge fan of Orleans, and have been for many years. Hopefully if there are misconceptions in any of the issues below those misconceptions can at least be useful insights for whomever is building docs to help devs successfully adopt Orleans.
Any update on this? seems like JsonElement is a common enough type for use in data transferring that it should be supported OOTB
I have same problem of "Orleans.Serialization.CodecNotFoundException : Could not find a codec" but in unit tests. It seems like It's impossible to write xunit tests with Microsoft.Orleans.TestingHost if in main project there are classes without GenerateSerializer attribute. I have project with common types: DomainObjects. Also I have let's say AllGrainsProject and TestsGrainsPoject (XUnit). Dependencies are follows: TestsGrainsPoject => AllGrainsProject =>DomainObjects
AllGrainsProject works fine by the help of
siloBuilder.ConfigureServices(services => { services.AddSerializer(serializerBuilder => { serializerBuilder.AddJsonSerializer(isSupported: type => type.Namespace.StartWith("DomainObjects");
But the same trick with TestClusterBuilder from Microsoft.Orleans.TestingHost doesn't work!
Approaches with [assembly: GenerateCodeForDeclaringAssembly(typeof(DomainObjects.ACD.RecordListLine))]
and IgnoreCycles in XUnit project didn't help at all!
@ilya-girman do you have Microsoft.Orleans.Sdk installed in your test project?
@ilya-girman @ReubenBond
I fixed this by adding 'AddSerializer' to both the silo and client configuration of the test cluster:
builder.AddSiloBuilderConfigurator<SiloBuilderConfigurator>();
builder.AddClientBuilderConfigurator<ClientBuilderConfigurator>();
private class SiloBuilderConfigurator : ISiloConfigurator
{
public void Configure(ISiloBuilder siloBuilder)
{
siloBuilder.Services.AddSerializer(serializerBuilder =>
{
serializerBuilder.AddNewtonsoftJsonSerializer(isSupported: type => true);
});
}
}
private class ClientBuilderConfigurator : IClientBuilderConfigurator
{
public void Configure(IConfiguration configuration, IClientBuilder clientBuilder)
{
clientBuilder.Services.AddSerializer(serializerBuilder =>
{
serializerBuilder.AddNewtonsoftJsonSerializer(isSupported: type => true);
});
}
}
@ReubenBond I have grain in my projects that accept CancellationToken
in the grain interface methods. What do you suggest for serializing these with the new Orleans version?
I have a Orleans 7.0 project with and I'm having an issue with the new default serializer.
The old serializer in Orleans 3.6.5 worked fine and it was serializing all the models and Dtos in the several internal Nuget packages.
Now in Orleans 7.0 the project does not recognize the models in the Nuget packages and I get this error:
Now for the interesting part: when I copy paste the exact same class in my main project I no longer get this error, and the class serializes perfectly fine.
I tried referencing the Nuget project directly in the main project(ProjectReference), the result is the same.
I only get rid of errors in two scenarios: