Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Er zijn in grote lijnen twee soorten serialisatie gebruikt in Orleans:
- Serialisatie van graanaanroepen: wordt gebruikt voor het serialiseren van objecten die worden doorgegeven aan en van granen.
- Serialisatie van graanopslag: wordt gebruikt voor het serialiseren van objecten naar en van opslagsystemen.
Het grootste deel van dit artikel richt zich op serialisatie van graanoproepen via het serialisatieframework dat is opgenomen in Orleans. In de sectie Grain Storage Serializers wordt de serialisatie van graanopslag besproken.
Serialisatie gebruiken Orleans
Orleans bevat een geavanceerd en uitbreidbaar serialisatieframework waarnaar wordt verwezen Orleans. Serialisatie. Het serialisatieframework dat is opgenomen in Orleans , is ontworpen om te voldoen aan de volgende doelstellingen:
- Hoge prestaties: de serializer is ontworpen en geoptimaliseerd voor prestaties. In deze presentatie vindt u meer informatie.
- Getrouwe weergave: De serializer vertegenwoordigt het grootste deel van het .NET-type systeem, inclusief ondersteuning voor generics, polymorfisme, overervingshiërarchieën, objectidentiteit en cyclische grafieken. Aanwijzers worden niet ondersteund omdat ze niet overdraagbaar zijn tussen processen.
- Flexibiliteit: u kunt de serialisatiefunctie aanpassen ter ondersteuning van bibliotheken van derden door surrogaten te maken of delegeren aan externe serialisatiebibliotheken zoals System.Text.Json, Newtonsoft.Json, MessagePack en Google.Protobuf.
-
Versietolerantie: Met de serializer kunnen toepassingstypen zich in de loop van de tijd ontwikkelen, waarbij ondersteuning wordt geboden voor:
- Leden toevoegen en verwijderen
- Subklassen
- Numerieke verbreding en vernauwing (bijvoorbeeld
intvan/naarlong,floatnaardouble) - Naamgevingstypen wijzigen
Hoogwaardige weergave van typen is vrij ongebruikelijk voor serializers, dus sommige punten rechtvaardigen verdere uitleg:
Dynamische typen en willekeurige polymorfisme: Orleans dwingt geen beperkingen af voor de typen die worden doorgegeven in graanoproepen en onderhoudt de dynamische aard van het werkelijke gegevenstype. nl-NL: Dit betekent bijvoorbeeld dat als een methode in een graaninterface wordt gedeclareerd om IDictionary te accepteren, maar de afzender tijdens runtime een SortedDictionary<TKey,TValue> doorgeeft, de ontvanger inderdaad een
SortedDictionaryontvangt (hoewel de "statische contract"/graaninterface dit gedrag niet specificeert).Objectidentiteit behouden: als hetzelfde object meerdere keren wordt doorgegeven in de argumenten van een korreloproep of indirect wordt verwezen naar meer dan één keer vanuit de argumenten, Orleans serialiseert u het slechts één keer. Herstelt aan de ontvangerzijde Orleans alle verwijzingen correct, zodat twee aanwijzers naar hetzelfde object na deserialisatie nog steeds naar hetzelfde object verwijzen. Het behouden van de objectidentiteit is belangrijk in scenario's zoals de volgende: Imagine grain A verzendt een woordenlijst met 100 vermeldingen naar korrel B en 10 sleutels in de woordenlijst verwijzen naar hetzelfde object,
objaan de zijde van A. Zonder de objectidentiteit te behouden, ontvangt B een woordenlijst van 100 vermeldingen met die 10 sleutels die verwijzen naar 10 verschillende klonen vanobj. Als de objectidentiteit behouden blijft, ziet de woordenlijst aan de zijkant van B er precies zo uit als aan de zijde van A, waarbij die 10 sleutels naar één objectobjwijzen. Houd er rekening mee dat de volgorde van waarden in woordenlijsten en hashsets (bijvoorbeeld) niet behouden blijft omdat de standaard-hashcode-implementaties in .NET willekeurig zijn per proces.
Ter ondersteuning van versietolerantie moet u voor de serialisatiefunctie expliciet zijn over welke typen en leden worden geserialiseerd. We hebben geprobeerd dit zo pijnloos mogelijk te maken. Markeer alle serialiseerbare typen met Orleans.GenerateSerializerAttribute om Orleans te instrueren om serialisatiecode voor uw type te genereren. Zodra u dit hebt gedaan, kunt u de opgenomen codefix gebruiken om de vereiste Orleans.IdAttribute toe te voegen aan de serialiseerbare leden van uw typen, zoals hier wordt weergegeven:
Hier is een voorbeeld van een serialiseerbaar type in Orleans, dat laat zien hoe u de kenmerken toepast.
[GenerateSerializer]
public class Employee
{
[Id(0)]
public string Name { get; set; }
}
Orleans ondersteunt overname en serialiseert de afzonderlijke lagen in de hiërarchie afzonderlijk, zodat ze afzonderlijke lid-id's kunnen hebben.
[GenerateSerializer]
public class Publication
{
[Id(0)]
public string Title { get; set; }
}
[GenerateSerializer]
public class Book : Publication
{
[Id(0)]
public string ISBN { get; set; }
}
In de voorgaande code moet u er rekening mee houden dat zowel Publication als Book leden met [Id(0)] hebben, ook al is Book afgeleid van Publication. Dit is de aanbevolen procedure Orleans omdat lididentificaties zijn begrensd tot het erfenniveau, niet het type als geheel. U kunt leden toevoegen aan en verwijderen uit Publication en Book onafhankelijk, maar u kunt geen nieuwe basisklasse invoegen in de hiërarchie zodra de toepassing is geïmplementeerd zonder speciale aandacht.
Orleans ondersteunt ook serialisatietypen met internal, privateen readonly leden, zoals in dit voorbeeldtype:
[GenerateSerializer]
public struct MyCustomStruct
{
public MyCustomStruct(int intProperty, int intField)
{
IntProperty = intProperty;
_intField = intField;
}
[Id(0)]
public int IntProperty { get; }
[Id(1)] private readonly int _intField;
public int GetIntField() => _intField;
public override string ToString() => $"{nameof(_intField)}: {_intField}, {nameof(IntProperty)}: {IntProperty}";
}
Standaard serialiseert Orleans uw type door de volledige naam te coderen. U kunt dit buiten werking stellen door een Orleans.AliasAttribute toe te voegen. Als u dit doet, wordt uw type geserialiseerd met behulp van een naam die tolerant is voor het wijzigen van de naam van de onderliggende klasse of het verplaatsen ervan tussen assembly's. Typealiassen zijn globaal gericht en u kunt geen twee aliassen met dezelfde waarde in een toepassing hebben. Voor generieke typen moet de aliaswaarde het aantal generieke parameters bevatten dat voorafgegaan wordt door een backtick; bijvoorbeeld kan MyGenericType<T, U> de alias [Alias("mytype`2")] hebben.
Typen serialiseren van record
Leden die zijn gedefinieerd in de primaire constructor van een record, hebben standaard impliciete id's. Met andere woorden, Orleans ondersteunt serialisatietypen record . Dit betekent dat u de parametervolgorde voor een al geïmplementeerd type niet kunt wijzigen, omdat dat de compatibiliteit met eerdere versies van uw toepassing (in een rolling upgradescenario) en met geserialiseerde exemplaren van dat type in opslag en streams wordt verbroken. Leden die zijn gedefinieerd in de hoofdtekst van een recordtype, delen geen identiteiten met de primaire constructorparameters.
[GenerateSerializer]
public record MyRecord(string A, string B)
{
// ID 0 won't clash with A in primary constructor as they don't share identities
[Id(0)]
public string C { get; init; }
}
Als u niet wilt dat de primaire constructorparameters automatisch worden opgenomen als serialiseerbare velden, gebruikt u [GenerateSerializer(IncludePrimaryConstructorParameters = false)].
Serialisatie van MessagePack
Orleans Vanaf 8.2 kunt u MessagePack gebruiken als een externe serializer voor Orleans. MessagePack is een hoogwaardige binaire serialisatie-indeling die kleinere nettoladingen produceert dan JSON, terwijl snelle serialisatie- en deserialisatiesnelheden behouden blijven.
Wanneer gebruikt u MessagePack?
Overweeg het gebruik van MessagePack wanneer:
- U hebt interoperabiliteit nodig met non-.NET systemen die Ondersteuning bieden voor MessagePack
- U hebt al typen voorzien van kenmerken van MessagePack (
[MessagePackObject],[Key]) - U wilt kleinere payloadgrootten in vergelijking met serializers op basis van JSON
- U hebt een gestandaardiseerde binaire indeling nodig
Voor de meeste Orleans toepassingen wordt de standaardserializer Orleans aanbevolen omdat deze hogere nauwkeurigheid biedt met ondersteuning voor het .NET-typesysteem, behoud van objectidentiteit en automatische generatie van serializers.
Het MessagePack Serializer-pakket installeren
Voeg het MessagePack-serializer-pakket toe aan uw project:
dotnet add package Microsoft.Orleans.Serialization.MessagePack
Serialisatie van MessagePack configureren
Als u MessagePack-serialisatie wilt configureren, gebruikt u de AddMessagePackSerializer extensiemethode:
public static void ConfigureMessagePackBasic(string[] args)
{
var builder = Host.CreateApplicationBuilder(args);
builder.UseOrleans(siloBuilder =>
{
siloBuilder.UseLocalhostClustering();
siloBuilder.Services.AddSerializer(serializerBuilder => serializerBuilder.AddMessagePackSerializer(
isSerializable: type => type.Namespace?.StartsWith("MyApp.Messages") == true,
isCopyable: type => false,
messagePackSerializerOptions: null
));
});
}
De isSerializable delegate bepaalt welke typen worden verwerkt door de MessagePack-serializer. Typen die niet overeenkomen met dit predicaat vallen terug op de standaardserialisatie Orleans .
MessagePackCodecOptions
U kunt de MessagePack-serializer configureren met behulp van MessagePackCodecOptions:
| Vastgoed | Typologie | Verstek | Description |
|---|---|---|---|
SerializerOptions |
MessagePackSerializerOptions |
MessagePackSerializerOptions.Standard |
De serialisatieopties van MessagePack die moeten worden gebruikt voor serialisatie. |
AllowDataContractAttributes |
bool |
false |
Wanneer true kunnen typen gemarkeerd met [DataContract] worden geserialiseerd met behulp van MessagePack. |
IsSerializableType |
Func<Type, bool?> |
null |
Een gemachtigde om te bepalen of een type moet worden geserialiseerd door MessagePack. |
IsCopyableType |
Func<Type, bool?> |
null |
Een gemachtigde om te bepalen of een type moet worden gekopieerd door MessagePack. |
Voorbeeld: Configureren met opties
public static void ConfigureMessagePackWithOptions(string[] args)
{
var builder = Host.CreateApplicationBuilder(args);
builder.UseOrleans(siloBuilder =>
{
siloBuilder.UseLocalhostClustering();
siloBuilder.Services.AddSerializer(serializerBuilder => serializerBuilder.AddMessagePackSerializer(
isSerializable: type => type.GetCustomAttribute<MessagePackObjectAttribute>() != null,
isCopyable: type => false,
configureOptions: options => options.Configure(opts =>
{
opts.SerializerOptions = MessagePackSerializerOptions.Standard
.WithCompression(MessagePackCompression.Lz4BlockArray);
opts.AllowDataContractAttributes = true;
})
));
});
}
MessagePack-typen definiëren
Typen die worden geserialiseerd door MessagePack moeten MessagePack-kenmerken gebruiken:
[MessagePackObject]
public class OrderMessage
{
[Key(0)]
public string OrderId { get; set; }
[Key(1)]
public decimal Amount { get; set; }
[Key(2)]
public DateTime CreatedAt { get; set; }
[Key(3)]
public List<string> Items { get; set; }
}
Vervolgens kunt u deze typen in graaninterfaces gebruiken:
public interface IOrderGrain : IGrainWithStringKey
{
Task<OrderMessage> GetOrder();
Task PlaceOrder(OrderMessage order);
}
Serializer-vergelijking
| Eigenschap | Orleans Native | MessagePack | System.Text.Json |
|---|---|---|---|
| Formaat | Binary | Binary | Tekst (JSON) |
| Betrouwbaarheid van .NET-type | Uitstekend | Goed | Beperkt |
| Objectidentiteit | Yes | Nee. | Nee. |
| Payloadgrootte | Klein | Kleinste | Grootste |
| Platformoverschrijdend | Alleen .NET | Elke MessagePack-client | Een JSON-client |
| Versietolerantie | Yes | Yes | Yes |
| Installatie vereist | Geen | Expliciete kenmerken | Expliciete kenmerken |
Surrogaten voor het serialiseren van externe typen
Soms moet u typen doorgeven tussen korrels waarvoor u geen volledige controle hebt. In dergelijke gevallen kan het handmatig converteren naar en van een aangepast gedefinieerd type in uw toepassingscode onpraktisch zijn. Orleans biedt een oplossing voor deze situaties: surrogaattypen. Surrogaten worden geserialiseerd in plaats van hun doeltype en hebben functionaliteit om van en naar het doeltype te converteren. Bekijk het volgende voorbeeld van een vreemd type en een bijbehorende surrogaat en omzetter:
// This is the foreign type, which you do not have control over.
public struct MyForeignLibraryValueType
{
public MyForeignLibraryValueType(int num, string str, DateTimeOffset dto)
{
Num = num;
String = str;
DateTimeOffset = dto;
}
public int Num { get; }
public string String { get; }
public DateTimeOffset DateTimeOffset { get; }
}
// This is the surrogate which will act as a stand-in for the foreign type.
// Surrogates should use plain fields instead of properties for better performance.
[GenerateSerializer]
public struct MyForeignLibraryValueTypeSurrogate
{
[Id(0)]
public int Num;
[Id(1)]
public string String;
[Id(2)]
public DateTimeOffset DateTimeOffset;
}
// This is a converter that converts between the surrogate and the foreign type.
[RegisterConverter]
public sealed class MyForeignLibraryValueTypeSurrogateConverter :
IConverter<MyForeignLibraryValueType, MyForeignLibraryValueTypeSurrogate>
{
public MyForeignLibraryValueType ConvertFromSurrogate(
in MyForeignLibraryValueTypeSurrogate surrogate) =>
new(surrogate.Num, surrogate.String, surrogate.DateTimeOffset);
public MyForeignLibraryValueTypeSurrogate ConvertToSurrogate(
in MyForeignLibraryValueType value) =>
new()
{
Num = value.Num,
String = value.String,
DateTimeOffset = value.DateTimeOffset
};
}
In de voorgaande code:
-
MyForeignLibraryValueTypeis een type buiten uw controle, gedefinieerd in een gebruikende bibliotheek. -
MyForeignLibraryValueTypeSurrogateis een surrogaattypetoewijzing aanMyForeignLibraryValueType. -
RegisterConverterAttribute geeft aan dat
MyForeignLibraryValueTypeSurrogateConverterfungeert als een converter om de twee typen aan elkaar te koppelen. De klasse implementeert de IConverter<TValue,TSurrogate> interface.
Orleans ondersteunt serialisatie van typen in typehiërarchieën (typen die zijn afgeleid van andere typen). Als een extern type kan worden weergegeven in een typehiërarchie (bijvoorbeeld als basisklasse voor een van uw eigen typen), moet u de Orleans.IPopulator<TValue,TSurrogate> interface ook implementeren. Kijk een naar het volgende voorbeeld:
// The foreign type is not sealed, allowing other types to inherit from it.
public class MyForeignLibraryType
{
public MyForeignLibraryType() { }
public MyForeignLibraryType(int num, string str, DateTimeOffset dto)
{
Num = num;
String = str;
DateTimeOffset = dto;
}
public int Num { get; set; }
public string String { get; set; }
public DateTimeOffset DateTimeOffset { get; set; }
}
// The surrogate is defined as it was in the previous example.
[GenerateSerializer]
public struct MyForeignLibraryTypeSurrogate
{
[Id(0)]
public int Num;
[Id(1)]
public string String;
[Id(2)]
public DateTimeOffset DateTimeOffset;
}
// Implement the IConverter and IPopulator interfaces on the converter.
[RegisterConverter]
public sealed class MyForeignLibraryTypeSurrogateConverter :
IConverter<MyForeignLibraryType, MyForeignLibraryTypeSurrogate>,
IPopulator<MyForeignLibraryType, MyForeignLibraryTypeSurrogate>
{
public MyForeignLibraryType ConvertFromSurrogate(
in MyForeignLibraryTypeSurrogate surrogate) =>
new(surrogate.Num, surrogate.String, surrogate.DateTimeOffset);
public MyForeignLibraryTypeSurrogate ConvertToSurrogate(
in MyForeignLibraryType value) =>
new()
{
Num = value.Num,
String = value.String,
DateTimeOffset = value.DateTimeOffset
};
public void Populate(
in MyForeignLibraryTypeSurrogate surrogate, MyForeignLibraryType value)
{
value.Num = surrogate.Num;
value.String = surrogate.String;
value.DateTimeOffset = surrogate.DateTimeOffset;
}
}
// Application types can inherit from the foreign type, assuming they're not sealed
// since Orleans knows how to serialize it.
[GenerateSerializer]
public sealed class DerivedFromMyForeignLibraryType : MyForeignLibraryType
{
public DerivedFromMyForeignLibraryType() { }
public DerivedFromMyForeignLibraryType(
int intValue, int num, string str, DateTimeOffset dto) : base(num, str, dto)
{
IntValue = intValue;
}
[Id(0)]
public int IntValue { get; set; }
}
Versiebeheerregels
Versietolerantie wordt ondersteund op voorwaarde dat u een set regels volgt bij het wijzigen van typen. Als u bekend bent met systemen zoals Google Protocol Buffers (Protobuf), zijn deze regels bekend.
Samengestelde typen (class & struct)
- Overname wordt ondersteund, maar het wijzigen van de overnamehiërarchie van een object wordt niet ondersteund. U kunt de basisklasse van een klasse niet toevoegen, wijzigen of verwijderen.
- Met uitzondering van sommige numerieke typen die worden beschreven in de sectie Numeriek hieronder, kunt u geen veldtypen wijzigen.
- U kunt velden toevoegen of verwijderen op elk moment in een overnamehiërarchie.
- U kunt geen veld-id's wijzigen.
- Veld-id's moeten uniek zijn voor elk niveau in een typehiërarchie, maar kunnen opnieuw worden gebruikt tussen basisklassen en subklassen. Een
Baseklasse kan bijvoorbeeld een veld met id0declareren en eenSub : Baseklasse kan een ander veld met dezelfde id declareren.0
Cijfers
- U kunt de ondertekening van een numeriek veld niet wijzigen.
- Conversies tussen
int&uintzijn ongeldig.
- Conversies tussen
- U kunt de breedte van een numeriek veld wijzigen.
- Conversies van
intnaarlongofulongnaarushortworden bijvoorbeeld ondersteund. - Conversies die de breedte beperken, genereren een uitzondering als de runtimewaarde van het veld een overloop veroorzaakt.
- Conversie van
ulongnaarushortwordt alleen ondersteund als de runtimewaarde kleiner is danushort.MaxValue. - Conversies van
doublenaarfloatworden alleen ondersteund als de runtimewaarde tussenfloat.MinValueenfloat.MaxValue. - Hetzelfde geldt voor
decimal, die een smaller bereik heeft dan beidedoubleenfloat.
- Conversies van
Kopieerapparaten
Orleans bevordert veiligheid als standaard, inclusief bescherming tegen bepaalde klassen van concurrerende fouten. Met name kopieert Orleans onmiddellijk objecten die standaard in grain-aanroepen worden doorgegeven. Orleans. Serialisatie vereenvoudigt dit kopiëren. Wanneer u Orleans.CodeGeneration.GenerateSerializerAttribute op een type toepast, genereert Orleans ook kopieerders voor dat type. Orleans vermijdt het kopiëren van typen of afzonderlijke leden die zijn gemarkeerd met ImmutableAttribute. Zie Serialisatie van onveranderbare typen in Orleansvoor meer informatie.
Best practices voor serialisatie
✅ Geef uw typen aliassen op met behulp van het
[Alias("my-type")]kenmerk. Typen met aliassen kunnen worden hernoemd zonder dat de compatibiliteit wordt onderbroken.❌ Verander een
recordniet in eenclassof omgekeerd. Records en klassen worden niet identiek weergegeven omdat records naast gewone leden primaire constructorleden hebben; daarom zijn de twee niet uitwisselbaar.❌ Voeg geen nieuwe typen toe aan een bestaande typehiërarchie voor een serialiseerbaar type. U mag geen nieuwe basisklasse toevoegen aan een bestaand type. U kunt veilig een nieuwe subklasse toevoegen aan een bestaand type.
✅ Vervang het gebruik van SerializableAttribute met GenerateSerializerAttribute en bijbehorende IdAttribute declaraties.
✅ Start alle leden-ID's op nul voor elk type. Id's in een subklasse en de basisklasse kunnen veilig overlappen. Beide eigenschappen in het volgende voorbeeld hebben id's gelijk aan
0.[GenerateSerializer] public class MyBaseClass { [Id(0)] public int MyBaseInt { get; set; } } [GenerateSerializer] public sealed class MySubClass : MyBaseClass { [Id(0)] public int MySubInt { get; set; } }✅ Verbreed numerieke datatypen indien nodig. U kunt
sbyteuitbreiden naarshort,intenlong.- U kunt numerieke lidtypen beperken, maar dit resulteert in een runtime-uitzondering als waargenomen waarden niet correct kunnen worden weergegeven door het beperkte type. Kan bijvoorbeeld
int.MaxValueniet worden vertegenwoordigd door eenshortveld, zodat het beperken van eenintveld datshortkan resulteren in een runtime-uitzondering als een dergelijke waarde wordt aangetroffen.
- U kunt numerieke lidtypen beperken, maar dit resulteert in een runtime-uitzondering als waargenomen waarden niet correct kunnen worden weergegeven door het beperkte type. Kan bijvoorbeeld
❌ Wijzig de ondertekening van een lid van het numerieke type niet . U mag een lidtype niet wijzigen van
uintnaarintof vanintnaaruint, bijvoorbeeld.
Serializers voor graanopslag
Orleans bevat een door een provider ondersteund persistentiemodel voor korrels, toegankelijk via de State eigenschap of door een of meer IPersistentState<TState> waarden in uw graan te injecteren. Vóór Orleans 7.0 had elke provider een ander mechanisme voor het configureren van serialisatie. In Orleans 7.0 is er nu een serialisatieinterface voor algemene statusstatussen, IGrainStorageSerializerdie een consistente manier biedt om statusserialisatie voor elke provider aan te passen. Ondersteunde opslagproviders implementeren een patroon met betrekking tot het instellen van de eigenschap in de IStorageProviderSerializerOptions.GrainStorageSerializer klasse Opties van de provider, bijvoorbeeld:
- DynamoDBStorageOptions.GrainStorageSerializer
- AzureBlobStorageOptions.GrainStorageSerializer
- AzureTableStorageOptions.GrainStorageSerializer
- GrainStorageSerializer
Opslagserialisatie voor graan is momenteel standaard ingesteld op Newtonsoft.Json om de status te serialiseren. U kunt deze vervangen door die eigenschap te wijzigen tijdens de configuratie. In het volgende voorbeeld ziet u dit met behulp van OptionsBuilder<TOptions>:
public static void ConfigureGrainStorageSerializer(ISiloBuilder siloBuilder)
{
siloBuilder.AddAzureBlobGrainStorage(
"MyGrainStorage",
(OptionsBuilder<AzureBlobStorageOptions> optionsBuilder) =>
{
optionsBuilder.Configure<MyCustomSerializer>(
(options, serializer) => options.GrainStorageSerializer = serializer);
});
}
Zie OptionsBuilder-API voor meer informatie.
Er zijn in grote lijnen twee soorten serialisatie gebruikt in Orleans:
- Serialisatie van graanaanroepen: wordt gebruikt voor het serialiseren van objecten die worden doorgegeven aan en van granen.
- Serialisatie van graanopslag: wordt gebruikt voor het serialiseren van objecten naar en van opslagsystemen.
Het grootste deel van dit artikel richt zich op serialisatie van graanoproepen via het serialisatieframework dat is opgenomen in Orleans. In de sectie Grain Storage Serializers wordt de serialisatie van graanopslag besproken.
Serialisatie gebruiken Orleans
Orleans bevat een geavanceerd en uitbreidbaar serialisatieframework waarnaar wordt verwezen Orleans. Serialisatie. Het serialisatieframework dat is opgenomen in Orleans , is ontworpen om te voldoen aan de volgende doelstellingen:
- Hoge prestaties: de serializer is ontworpen en geoptimaliseerd voor prestaties. In deze presentatie vindt u meer informatie.
- Getrouwe weergave: De serializer vertegenwoordigt het grootste deel van het .NET-type systeem, inclusief ondersteuning voor generics, polymorfisme, overervingshiërarchieën, objectidentiteit en cyclische grafieken. Aanwijzers worden niet ondersteund omdat ze niet overdraagbaar zijn tussen processen.
- Flexibiliteit: u kunt de serialisatiefunctie aanpassen ter ondersteuning van bibliotheken van derden door surrogaten te maken of delegeren aan externe serialisatiebibliotheken zoals System.Text.Json, Newtonsoft.Json en Google.Protobuf.
-
Versietolerantie: Met de serializer kunnen toepassingstypen zich in de loop van de tijd ontwikkelen, waarbij ondersteuning wordt geboden voor:
- Leden toevoegen en verwijderen
- Subklassen
- Numerieke verbreding en vernauwing (bijvoorbeeld
intvan/naarlong,floatnaardouble) - Naamgevingstypen wijzigen
Hoogwaardige weergave van typen is vrij ongebruikelijk voor serializers, dus sommige punten rechtvaardigen verdere uitleg:
Dynamische typen en willekeurige polymorfisme: Orleans dwingt geen beperkingen af voor de typen die worden doorgegeven in graanoproepen en onderhoudt de dynamische aard van het werkelijke gegevenstype. nl-NL: Dit betekent bijvoorbeeld dat als een methode in een graaninterface wordt gedeclareerd om IDictionary te accepteren, maar de afzender tijdens runtime een SortedDictionary<TKey,TValue> doorgeeft, de ontvanger inderdaad een
SortedDictionaryontvangt (hoewel de "statische contract"/graaninterface dit gedrag niet specificeert).Objectidentiteit behouden: als hetzelfde object meerdere keren wordt doorgegeven in de argumenten van een korreloproep of indirect wordt verwezen naar meer dan één keer vanuit de argumenten, Orleans serialiseert u het slechts één keer. Herstelt aan de ontvangerzijde Orleans alle verwijzingen correct, zodat twee aanwijzers naar hetzelfde object na deserialisatie nog steeds naar hetzelfde object verwijzen. Het behouden van de objectidentiteit is belangrijk in scenario's zoals de volgende: Imagine grain A verzendt een woordenlijst met 100 vermeldingen naar korrel B en 10 sleutels in de woordenlijst verwijzen naar hetzelfde object,
objaan de zijde van A. Zonder de objectidentiteit te behouden, ontvangt B een woordenlijst van 100 vermeldingen met die 10 sleutels die verwijzen naar 10 verschillende klonen vanobj. Als de objectidentiteit behouden blijft, ziet de woordenlijst aan de zijkant van B er precies zo uit als aan de zijde van A, waarbij die 10 sleutels naar één objectobjwijzen. Houd er rekening mee dat de volgorde van waarden in woordenlijsten en hashsets (bijvoorbeeld) niet behouden blijft omdat de standaard-hashcode-implementaties in .NET willekeurig zijn per proces.
Ter ondersteuning van versietolerantie moet u voor de serialisatiefunctie expliciet zijn over welke typen en leden worden geserialiseerd. We hebben geprobeerd dit zo pijnloos mogelijk te maken. Markeer alle serialiseerbare typen met Orleans.GenerateSerializerAttribute om Orleans te instrueren om serialisatiecode voor uw type te genereren. Zodra u dit hebt gedaan, kunt u de opgenomen codefix gebruiken om de vereiste Orleans.IdAttribute toe te voegen aan de serialiseerbare leden van uw typen, zoals hier wordt weergegeven:
Hier is een voorbeeld van een serialiseerbaar type in Orleans, dat laat zien hoe u de kenmerken toepast.
[GenerateSerializer]
public class Employee
{
[Id(0)]
public string Name { get; set; }
}
Orleans ondersteunt overname en serialiseert de afzonderlijke lagen in de hiërarchie afzonderlijk, zodat ze afzonderlijke lid-id's kunnen hebben.
[GenerateSerializer]
public class Publication
{
[Id(0)]
public string Title { get; set; }
}
[GenerateSerializer]
public class Book : Publication
{
[Id(0)]
public string ISBN { get; set; }
}
In de voorgaande code moet u er rekening mee houden dat zowel Publication als Book leden met [Id(0)] hebben, ook al is Book afgeleid van Publication. Dit is de aanbevolen procedure Orleans omdat lididentificaties zijn begrensd tot het erfenniveau, niet het type als geheel. U kunt leden toevoegen aan en verwijderen uit Publication en Book onafhankelijk, maar u kunt geen nieuwe basisklasse invoegen in de hiërarchie zodra de toepassing is geïmplementeerd zonder speciale aandacht.
Orleans ondersteunt ook serialisatietypen met internal, privateen readonly leden, zoals in dit voorbeeldtype:
[GenerateSerializer]
public struct MyCustomStruct
{
public MyCustom(int intProperty, int intField)
{
IntProperty = intProperty;
_intField = intField;
}
[Id(0)]
public int IntProperty { get; }
[Id(1)] private readonly int _intField;
public int GetIntField() => _intField;
public override string ToString() => $"{nameof(_intField)}: {_intField}, {nameof(IntProperty)}: {IntProperty}";
}
Standaard serialiseert Orleans uw type door de volledige naam te coderen. U kunt dit buiten werking stellen door een Orleans.AliasAttribute toe te voegen. Als u dit doet, wordt uw type geserialiseerd met behulp van een naam die tolerant is voor het wijzigen van de naam van de onderliggende klasse of het verplaatsen ervan tussen assembly's. Typealiassen zijn globaal gericht en u kunt geen twee aliassen met dezelfde waarde in een toepassing hebben. Voor generieke typen moet de aliaswaarde het aantal generieke parameters bevatten dat voorafgegaan wordt door een backtick; bijvoorbeeld kan MyGenericType<T, U> de alias [Alias("mytype`2")] hebben.
Typen serialiseren van record
Leden die zijn gedefinieerd in de primaire constructor van een record, hebben standaard impliciete id's. Met andere woorden, Orleans ondersteunt serialisatietypen record . Dit betekent dat u de parametervolgorde voor een al geïmplementeerd type niet kunt wijzigen, omdat dat de compatibiliteit met eerdere versies van uw toepassing (in een rolling upgradescenario) en met geserialiseerde exemplaren van dat type in opslag en streams wordt verbroken. Leden die zijn gedefinieerd in de hoofdtekst van een recordtype, delen geen identiteiten met de primaire constructorparameters.
[GenerateSerializer]
public record MyRecord(string A, string B)
{
// ID 0 won't clash with A in primary constructor as they don't share identities
[Id(0)]
public string C { get; init; }
}
Als u niet wilt dat de primaire constructorparameters automatisch worden opgenomen als serialiseerbare velden, gebruikt u [GenerateSerializer(IncludePrimaryConstructorParameters = false)].
Surrogaten voor het serialiseren van externe typen
Soms moet u typen doorgeven tussen korrels waarvoor u geen volledige controle hebt. In dergelijke gevallen kan het handmatig converteren naar en van een aangepast gedefinieerd type in uw toepassingscode onpraktisch zijn. Orleans biedt een oplossing voor deze situaties: surrogaattypen. Surrogaten worden geserialiseerd in plaats van hun doeltype en hebben functionaliteit om van en naar het doeltype te converteren. Bekijk het volgende voorbeeld van een vreemd type en een bijbehorende surrogaat en omzetter:
// This is the foreign type, which you do not have control over.
public struct MyForeignLibraryValueType
{
public MyForeignLibraryValueType(int num, string str, DateTimeOffset dto)
{
Num = num;
String = str;
DateTimeOffset = dto;
}
public int Num { get; }
public string String { get; }
public DateTimeOffset DateTimeOffset { get; }
}
// This is the surrogate which will act as a stand-in for the foreign type.
// Surrogates should use plain fields instead of properties for better performance.
[GenerateSerializer]
public struct MyForeignLibraryValueTypeSurrogate
{
[Id(0)]
public int Num;
[Id(1)]
public string String;
[Id(2)]
public DateTimeOffset DateTimeOffset;
}
// This is a converter that converts between the surrogate and the foreign type.
[RegisterConverter]
public sealed class MyForeignLibraryValueTypeSurrogateConverter :
IConverter<MyForeignLibraryValueType, MyForeignLibraryValueTypeSurrogate>
{
public MyForeignLibraryValueType ConvertFromSurrogate(
in MyForeignLibraryValueTypeSurrogate surrogate) =>
new(surrogate.Num, surrogate.String, surrogate.DateTimeOffset);
public MyForeignLibraryValueTypeSurrogate ConvertToSurrogate(
in MyForeignLibraryValueType value) =>
new()
{
Num = value.Num,
String = value.String,
DateTimeOffset = value.DateTimeOffset
};
}
In de voorgaande code:
-
MyForeignLibraryValueTypeis een type buiten uw controle, gedefinieerd in een gebruikende bibliotheek. -
MyForeignLibraryValueTypeSurrogateis een surrogaattypetoewijzing aanMyForeignLibraryValueType. -
RegisterConverterAttribute geeft aan dat
MyForeignLibraryValueTypeSurrogateConverterfungeert als een converter om de twee typen aan elkaar te koppelen. De klasse implementeert de IConverter<TValue,TSurrogate> interface.
Orleans ondersteunt serialisatie van typen in typehiërarchieën (typen die zijn afgeleid van andere typen). Als een extern type kan worden weergegeven in een typehiërarchie (bijvoorbeeld als basisklasse voor een van uw eigen typen), moet u de Orleans.IPopulator<TValue,TSurrogate> interface ook implementeren. Kijk een naar het volgende voorbeeld:
// The foreign type is not sealed, allowing other types to inherit from it.
public class MyForeignLibraryType
{
public MyForeignLibraryType() { }
public MyForeignLibraryType(int num, string str, DateTimeOffset dto)
{
Num = num;
String = str;
DateTimeOffset = dto;
}
public int Num { get; set; }
public string String { get; set; }
public DateTimeOffset DateTimeOffset { get; set; }
}
// The surrogate is defined as it was in the previous example.
[GenerateSerializer]
public struct MyForeignLibraryTypeSurrogate
{
[Id(0)]
public int Num;
[Id(1)]
public string String;
[Id(2)]
public DateTimeOffset DateTimeOffset;
}
// Implement the IConverter and IPopulator interfaces on the converter.
[RegisterConverter]
public sealed class MyForeignLibraryTypeSurrogateConverter :
IConverter<MyForeignLibraryType, MyForeignLibraryTypeSurrogate>,
IPopulator<MyForeignLibraryType, MyForeignLibraryTypeSurrogate>
{
public MyForeignLibraryType ConvertFromSurrogate(
in MyForeignLibraryTypeSurrogate surrogate) =>
new(surrogate.Num, surrogate.String, surrogate.DateTimeOffset);
public MyForeignLibraryTypeSurrogate ConvertToSurrogate(
in MyForeignLibraryType value) =>
new()
{
Num = value.Num,
String = value.String,
DateTimeOffset = value.DateTimeOffset
};
public void Populate(
in MyForeignLibraryTypeSurrogate surrogate, MyForeignLibraryType value)
{
value.Num = surrogate.Num;
value.String = surrogate.String;
value.DateTimeOffset = surrogate.DateTimeOffset;
}
}
// Application types can inherit from the foreign type, assuming they're not sealed
// since Orleans knows how to serialize it.
[GenerateSerializer]
public sealed class DerivedFromMyForeignLibraryType : MyForeignLibraryType
{
public DerivedFromMyForeignLibraryType() { }
public DerivedFromMyForeignLibraryType(
int intValue, int num, string str, DateTimeOffset dto) : base(num, str, dto)
{
IntValue = intValue;
}
[Id(0)]
public int IntValue { get; set; }
}
Versiebeheerregels
Versietolerantie wordt ondersteund op voorwaarde dat u een set regels volgt bij het wijzigen van typen. Als u bekend bent met systemen zoals Google Protocol Buffers (Protobuf), zijn deze regels bekend.
Samengestelde typen (class & struct)
- Overname wordt ondersteund, maar het wijzigen van de overnamehiërarchie van een object wordt niet ondersteund. U kunt de basisklasse van een klasse niet toevoegen, wijzigen of verwijderen.
- Met uitzondering van sommige numerieke typen die worden beschreven in de sectie Numeriek hieronder, kunt u geen veldtypen wijzigen.
- U kunt velden toevoegen of verwijderen op elk moment in een overnamehiërarchie.
- U kunt geen veld-id's wijzigen.
- Veld-id's moeten uniek zijn voor elk niveau in een typehiërarchie, maar kunnen opnieuw worden gebruikt tussen basisklassen en subklassen. Een
Baseklasse kan bijvoorbeeld een veld met id0declareren en eenSub : Baseklasse kan een ander veld met dezelfde id declareren.0
Cijfers
- U kunt de ondertekening van een numeriek veld niet wijzigen.
- Conversies tussen
int&uintzijn ongeldig.
- Conversies tussen
- U kunt de breedte van een numeriek veld wijzigen.
- Conversies van
intnaarlongofulongnaarushortworden bijvoorbeeld ondersteund. - Conversies die de breedte beperken, genereren een uitzondering als de runtimewaarde van het veld een overloop veroorzaakt.
- Conversie van
ulongnaarushortwordt alleen ondersteund als de runtimewaarde kleiner is danushort.MaxValue. - Conversies van
doublenaarfloatworden alleen ondersteund als de runtimewaarde tussenfloat.MinValueenfloat.MaxValue. - Hetzelfde geldt voor
decimal, die een smaller bereik heeft dan beidedoubleenfloat.
- Conversies van
Kopieerapparaten
Orleans bevordert veiligheid als standaard, inclusief bescherming tegen bepaalde klassen van concurrerende fouten. Met name kopieert Orleans onmiddellijk objecten die standaard in grain-aanroepen worden doorgegeven. Orleans. Serialisatie vereenvoudigt dit kopiëren. Wanneer u Orleans.CodeGeneration.GenerateSerializerAttribute op een type toepast, genereert Orleans ook kopieerders voor dat type. Orleans vermijdt het kopiëren van typen of afzonderlijke leden die zijn gemarkeerd met ImmutableAttribute. Zie Serialisatie van onveranderbare typen in Orleansvoor meer informatie.
Best practices voor serialisatie
✅ Geef uw typen aliassen op met behulp van het
[Alias("my-type")]kenmerk. Typen met aliassen kunnen worden hernoemd zonder dat de compatibiliteit wordt onderbroken.❌ Verander een
recordniet in eenclassof omgekeerd. Records en klassen worden niet identiek weergegeven omdat records naast gewone leden primaire constructorleden hebben; daarom zijn de twee niet uitwisselbaar.❌ Voeg geen nieuwe typen toe aan een bestaande typehiërarchie voor een serialiseerbaar type. U mag geen nieuwe basisklasse toevoegen aan een bestaand type. U kunt veilig een nieuwe subklasse toevoegen aan een bestaand type.
✅ Vervang het gebruik van SerializableAttribute met GenerateSerializerAttribute en bijbehorende IdAttribute declaraties.
✅ Start alle leden-ID's op nul voor elk type. Id's in een subklasse en de basisklasse kunnen veilig overlappen. Beide eigenschappen in het volgende voorbeeld hebben id's gelijk aan
0.[GenerateSerializer] public sealed class MyBaseClass { [Id(0)] public int MyBaseInt { get; set; } } [GenerateSerializer] public sealed class MySubClass : MyBaseClass { [Id(0)] public int MyBaseInt { get; set; } }✅ Verbreed numerieke datatypen indien nodig. U kunt
sbyteuitbreiden naarshort,intenlong.- U kunt numerieke lidtypen beperken, maar dit resulteert in een runtime-uitzondering als waargenomen waarden niet correct kunnen worden weergegeven door het beperkte type. Kan bijvoorbeeld
int.MaxValueniet worden vertegenwoordigd door eenshortveld, zodat het beperken van eenintveld datshortkan resulteren in een runtime-uitzondering als een dergelijke waarde wordt aangetroffen.
- U kunt numerieke lidtypen beperken, maar dit resulteert in een runtime-uitzondering als waargenomen waarden niet correct kunnen worden weergegeven door het beperkte type. Kan bijvoorbeeld
❌ Wijzig de ondertekening van een lid van het numerieke type niet . U mag een lidtype niet wijzigen van
uintnaarintof vanintnaaruint, bijvoorbeeld.
Serializers voor graanopslag
Orleans bevat een door een provider ondersteund persistentiemodel voor korrels, toegankelijk via de State eigenschap of door een of meer IPersistentState<TState> waarden in uw graan te injecteren. Vóór Orleans 7.0 had elke provider een ander mechanisme voor het configureren van serialisatie. In Orleans 7.0 is er nu een serialisatieinterface voor algemene statusstatussen, IGrainStorageSerializerdie een consistente manier biedt om statusserialisatie voor elke provider aan te passen. Ondersteunde opslagproviders implementeren een patroon met betrekking tot het instellen van de eigenschap in de IStorageProviderSerializerOptions.GrainStorageSerializer klasse Opties van de provider, bijvoorbeeld:
- DynamoDBStorageOptions.GrainStorageSerializer
- AzureBlobStorageOptions.GrainStorageSerializer
- AzureTableStorageOptions.GrainStorageSerializer
- GrainStorageSerializer
Opslagserialisatie voor graan is momenteel standaard ingesteld op Newtonsoft.Json om de status te serialiseren. U kunt deze vervangen door die eigenschap te wijzigen tijdens de configuratie. In het volgende voorbeeld ziet u dit met behulp van OptionsBuilder<TOptions>:
siloBuilder.AddAzureBlobGrainStorage(
"MyGrainStorage",
(OptionsBuilder<AzureBlobStorageOptions> optionsBuilder) =>
{
optionsBuilder.Configure<IMySerializer>(
(options, serializer) => options.GrainStorageSerializer = serializer);
});
Zie OptionsBuilder-API voor meer informatie.
Orleans heeft een geavanceerd en uitbreidbaar serialisatieframework. Orleans serialiseert gegevenstypen die worden doorgegeven in grain-aanvraag- en antwoordberichten, evenals grain-objecten voor permanente status. Als onderdeel van dit framework Orleans genereert u automatisch serialisatiecode voor deze gegevenstypen. Naast het genereren van efficiëntere serialisatie/deserialisatie voor typen die al .NET-serializeerbaar zijn, probeert Orleans ook serialisatieprogramma's te genereren voor typen die worden gebruikt in graaninterfaces en niet .NET-serializeerbaar zijn. Het framework bevat ook een set efficiënte ingebouwde serializers voor veelgebruikte typen: lijsten, woordenlijsten, tekenreeksen, primitieven, matrices, enzovoort.
Twee belangrijke functies van de Orleans-serializer onderscheiden het van vele andere derde-partij serialisatieframeworks: dynamische typen/arbitrair polymorfisme en objectidentiteit.
Dynamische typen en willekeurige polymorfisme: Orleans dwingt geen beperkingen af voor de typen die worden doorgegeven in graanoproepen en onderhoudt de dynamische aard van het werkelijke gegevenstype. nl-NL: Dit betekent bijvoorbeeld dat als een methode in een graaninterface wordt gedeclareerd om IDictionary te accepteren, maar de afzender tijdens runtime een SortedDictionary<TKey,TValue> doorgeeft, de ontvanger inderdaad een
SortedDictionaryontvangt (hoewel de "statische contract"/graaninterface dit gedrag niet specificeert).Objectidentiteit behouden: als hetzelfde object meerdere keren wordt doorgegeven in de argumenten van een korreloproep of indirect wordt verwezen naar meer dan één keer vanuit de argumenten, Orleans serialiseert u het slechts één keer. Herstelt aan de ontvangerzijde Orleans alle verwijzingen correct, zodat twee aanwijzers naar hetzelfde object na deserialisatie nog steeds naar hetzelfde object verwijzen. Het behouden van de objectidentiteit is belangrijk in scenario's zoals de volgende: Imagine grain A verzendt een woordenlijst met 100 vermeldingen naar korrel B en 10 sleutels in de woordenlijst verwijzen naar hetzelfde object,
objaan de zijde van A. Zonder de objectidentiteit te behouden, ontvangt B een woordenlijst van 100 vermeldingen met die 10 sleutels die verwijzen naar 10 verschillende klonen vanobj. Als de objectidentiteit behouden blijft, ziet de woordenlijst aan de zijkant van B er precies zo uit als aan de zijde van A, waarbij die 10 sleutels naar één objectobjwijzen.
De standaard .NET binaire serializer biedt de bovenstaande twee gedragingen, dus het was belangrijk voor ons om dit standaard en vertrouwde gedrag ook Orleans te ondersteunen.
Gegenereerde serializers
Orleans gebruikt de volgende regels om te bepalen welke serializers moeten worden gegenereerd:
- Scan alle typen in alle assembly's die verwijzen naar de kernbibliotheek Orleans .
- Genereer vanuit deze assemblies serialisatoren voor typen die rechtstreeks worden verwezen in grain interface method signatures of state class signatures, of voor elk type dat is gemarkeerd met SerializableAttribute.
- Daarnaast kan een grain-interface of implementatieproject wijzen op willekeurige typen voor het genereren van serialisatie door attributen op assemblyniveau toe te voegen, zoals KnownTypeAttribute of KnownAssemblyAttribute. Deze vertellen de codegenerator dat er serializers moeten worden gegenereerd voor specifieke typen of alle in aanmerking komende typen binnen een assembly. Voor meer informatie over assemblage-kenmerken, zie Kenmerken toepassen op het assemblageniveau.
Nood-serialisatie
Orleans ondersteunt de overdracht van willekeurige typen tijdens runtime. Daarom kan de ingebouwde codegenerator niet de volledige set typen bepalen die van tevoren worden verzonden. Bovendien kunnen bepaalde typen geen serialisatieprogramma's voor deze typen hebben, omdat ze niet toegankelijk zijn (bijvoorbeeld private) of niet-toegankelijke velden hebben (bijvoorbeeld readonly). Er is dus behoefte aan Just-In-Time-serialisatie van typen die onverwacht waren of geen serialisatieprogramma's konden hebben die vooraf werden gegenereerd. De serializer die verantwoordelijk is voor deze typen wordt de fallback-serializer genoemd.
Orleans wordt geleverd met twee fallback-serializers.
- Orleans.Serialization.BinaryFormatterSerializer, die gebruikmaakt van . NET's BinaryFormatter; en
-
Orleans.Serialization.ILBasedSerializer, waarmee tijdens runtime CIL-instructies worden gegenereerd om een serialisator te creëren die gebruikmaakt van 's serialisatieframework om elk veld te serialiseren. Dit betekent dat als een niet-toegankelijk type
MyPrivateTypeeen veldMyTypebevat dat een aangepaste serialisatiefunctie heeft, die aangepaste serialisatiefunctie wordt gebruikt om het te serialiseren.
Configureer de fallback-serializer met behulp van de FallbackSerializationProvider eigenschap op zowel ClientConfiguration (client) als GlobalConfiguration (silo's).
// Client configuration
var clientConfiguration = new ClientConfiguration();
clientConfiguration.FallbackSerializationProvider =
typeof(FantasticSerializer).GetTypeInfo();
// Global configuration
var globalConfiguration = new GlobalConfiguration();
globalConfiguration.FallbackSerializationProvider =
typeof(FantasticSerializer).GetTypeInfo();
U kunt ook de terugvalsserialisatieprovider opgeven in de XML-configuratie:
<Messaging>
<FallbackSerializationProvider
Type="GreatCompany.FantasticFallbackSerializer, GreatCompany.SerializerAssembly"/>
</Messaging>
De BinaryFormatterSerializer is de standaard fallback serializer.
Waarschuwing
Binaire serialisatie met BinaryFormatter kan gevaarlijk zijn. Zie de beveiligingshandleiding binaryFormatter en de binaryFormatter-migratiehandleiding voor meer informatie.
Serialisatie van uitzonderingen
Uitzonderingen worden geserialiseerd met behulp van de terugvalsserialisatie. Met de standaardconfiguratie, BinaryFormatter is de fallback-serializer. Daarom moet u het ISerializable-patroon volgen om ervoor te zorgen dat alle eigenschappen in een uitzonderingstype correct worden geserialiseerd.
Hier volgt een voorbeeld van een uitzonderingstype met correct geïmplementeerde serialisatie:
[Serializable]
public class MyCustomException : Exception
{
public string MyProperty { get; }
public MyCustomException(string myProperty, string message)
: base(message)
{
MyProperty = myProperty;
}
public MyCustomException(string transactionId, string message, Exception innerException)
: base(message, innerException)
{
MyProperty = transactionId;
}
// Note: This is the constructor called by BinaryFormatter during deserialization
public MyCustomException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
MyProperty = info.GetString(nameof(MyProperty));
}
// Note: This method is called by BinaryFormatter during serialization
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue(nameof(MyProperty), MyProperty);
}
}
Best practices voor serialisatie
Serialisatie dient voor twee primaire doeleinden in Orleans:
- Als draadindeling voor het verzenden van gegevens tussen korrels en clients tijdens runtime.
- Als opslagindeling voor het behouden van gegevens met een lange levensduur voor later ophalen.
De serializers die door Orleans zijn gegenereerd, zijn geschikt voor het eerste doel vanwege hun flexibiliteit, prestaties en veelzijdigheid. Ze zijn niet zo geschikt voor het tweede doel, omdat ze niet expliciet versietolerant zijn. U wordt aangeraden een versietolerante serializer, zoals ProtocolBuffers, te configureren voor permanente gegevens. Protocol Buffers worden ondersteund via Orleans.Serialization.ProtobufSerializer vanuit het Microsoft.Orleans.OrleansGoogleUtils NuGet-pakket. Volg de aanbevolen procedures voor uw gekozen serializer om versietolerantie te garanderen. Configureer serializers van derden met behulp van de SerializationProviders configuratie-eigenschap zoals hierboven beschreven.