What is the approach for non-POCOs in 4.X #7569
Replies: 6 comments 47 replies
-
Hi Sebastian, could you elaborate? |
Beta Was this translation helpful? Give feedback.
-
A surrogate can be used in place of the original type. Below is an example of creating a serializer for a type which cannot be annotated because it comes from an assembly which you don't own. The general pattern is to create a surrogate type, have Orleans generate a serializer for that, and then create a converter. In the example below, I've also defined a copier. Often times, the type is immutable, so the copier can simply return the input. [RegisterSerializer]
public sealed class UriCodec : GeneralizedReferenceTypeSurrogateCodec<Uri, UriSurrogate>
{
private readonly TypeConverter _uriConverter = TypeDescriptor.GetConverter(typeof(Uri));
public UriCodec(IValueSerializer<UriSurrogate> surrogateSerializer) : base(surrogateSerializer)
{
}
public override Uri ConvertFromSurrogate(ref UriSurrogate surrogate) => surrogate.Value switch
{
null => null,
_ => (Uri)_uriConverter.ConvertFromInvariantString(surrogate.Value)
};
public override void ConvertToSurrogate(Uri value, ref UriSurrogate surrogate) => surrogate = value switch
{
null => default,
_ => new UriSurrogate
{
Value = _uriConverter.ConvertToInvariantString(value)
},
};
}
[GenerateSerializer]
public struct UriSurrogate
{
[Id(1)]
public string Value { get; set; }
}
[RegisterCopier]
public sealed class UriCopier : IDeepCopier<Uri>, IGeneralizedCopier
{
public Uri DeepCopy(Uri input, CopyContext context) => input;
// Uri has derived types and these are handled by declaring this as a "generalized copier" which
// knows how to copy them. Usually, you don't need to do this. The "System.Type" type also needs something similar
public object DeepCopy(object input, CopyContext context) => input;
public bool IsSupportedType(Type type) => typeof(Uri).IsAssignableFrom(type);
} Note that if the type lives in an assembly which you do own, then you have the option of annotating the type using the correct attributes but generating code in a separate assembly. In order to accomplish that, the assembly with the types should not have the code generator installed (only Microsoft.Orleans.Serialization.Abstractions), and another assembly should have both the code generator installed as well as an attribute in the form of |
Beta Was this translation helpful? Give feedback.
-
Btw: What is the approach for Exceptions? The old ISerializable thing? |
Beta Was this translation helpful? Give feedback.
-
What about using a CustomReflectionContext ( https://docs.microsoft.com/en-us/dotnet/api/system.reflection.context.customreflectioncontext?view=dotnet-plat-ext-6.0 ) to synthesize the [GenerateSerializer] and [Id] attributes needed? This would allow Hagar to remain mostly unmolested -- you'd have to provide an way to provide an optional reflection context -- while allowing a configuration - maybe a manifest config text file - which explains how to annotate external types for which you don't have the source. |
Beta Was this translation helpful? Give feedback.
-
Related question, are there plans on properly supporting record types? Currently we'll have to define al Members explicitly and mark them with an Id attribute, e.g. [GenerateSerializer]
record Person(string FirstName, string LastName) {
[Id(0)]
public string FirstName { get; init; }
[Id(1)]
public string LastName { get; init; }
[Id(2)]
public string? MiddleName { get; init; }
} This could hypothetically be simplified to something in the lines of: [GenerateSerializer]
record Person(string FirstName, string LastName) {
[Id(0)]
public string? MiddleName { get; init; }
} Where Orleans codegen automatically includes primary constructor arguments before including marked properties. Version tolerance will still be a thing since changing the primary constructor would be a breaking change anyway. |
Beta Was this translation helpful? Give feedback.
-
This is a foot gun. A plain |
Beta Was this translation helpful? Give feedback.
-
Hi,
The Release describes what to do with POCOs. But what is the approach for Value types and collections and everything else that is not a POCO?
I understand how POCOs get serialized. You loop over all the properties and then you have default serializers for the most common value types (DateTime, Date, Guid and so on) and collections (List, Dictionary, HashSet ...).
But what is, when I have types, that I cannot annotate, for example a custom value type for a Guid, or NodaTime. In 3.X it works, because the underlaying fields are often serialized (in my understanding). But what do I have to do now? Is there a new interface for a custom converter / serializer?
Beta Was this translation helpful? Give feedback.
All reactions