From b20f3df595f063d1dd059c45a459df4cf16e9de9 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Mon, 24 May 2021 22:30:13 -0700 Subject: [PATCH] feat(codegen): Adds AfterDeserialization support (#615) Added the ability to execute arbitrary code after deserialization. Example, let's say you want to delete an item after you deserialize it: ```cs [AfterDeserialization] private void OnAfterDeserialization() { Delete(); } ``` Generates this: ```cs public override void Deserialize(IGenericReader reader) { base.Deserialize(reader); var version = reader.ReadEncodedInt(); Timer.DelayCall(OnAfterDeserialization); } ``` --- .../SerializableEntityGeneration.Class.cs | 1 + ...zableEntityGeneration.DeserializeMethod.cs | 26 +++++++++++++++++ ...ializableEntityGeneration.MetadataTypes.cs | 1 + .../Serialization/AfterDeserialization.cs | 28 +++++++++++++++++++ 4 files changed, 56 insertions(+) create mode 100644 Projects/Server/Serialization/AfterDeserialization.cs diff --git a/Projects/SerializationGenerator/SerializableEntityGeneration/SerializableEntityGeneration.Class.cs b/Projects/SerializationGenerator/SerializableEntityGeneration/SerializableEntityGeneration.Class.cs index c50a40d4f..5498e3c2b 100644 --- a/Projects/SerializationGenerator/SerializableEntityGeneration/SerializableEntityGeneration.Class.cs +++ b/Projects/SerializationGenerator/SerializableEntityGeneration/SerializableEntityGeneration.Class.cs @@ -236,6 +236,7 @@ namespace SerializationGenerator // Deserialize Method source.GenerateDeserializeMethod( compilation, + classSymbol, isOverride, version, encodedVersion, diff --git a/Projects/SerializationGenerator/SerializableEntityGeneration/SerializableEntityGeneration.DeserializeMethod.cs b/Projects/SerializationGenerator/SerializableEntityGeneration/SerializableEntityGeneration.DeserializeMethod.cs index 10723278d..94bbe8d97 100644 --- a/Projects/SerializationGenerator/SerializableEntityGeneration/SerializableEntityGeneration.DeserializeMethod.cs +++ b/Projects/SerializationGenerator/SerializableEntityGeneration/SerializableEntityGeneration.DeserializeMethod.cs @@ -15,6 +15,7 @@ using System.Collections.Generic; using System.Collections.Immutable; +using System.Linq; using System.Text; using Microsoft.CodeAnalysis; @@ -25,6 +26,7 @@ namespace SerializationGenerator public static void GenerateDeserializeMethod( this StringBuilder source, Compilation compilation, + INamedTypeSymbol classSymbol, bool isOverride, int version, bool encodedVersion, @@ -47,6 +49,7 @@ namespace SerializationGenerator if (isOverride) { source.AppendLine($"{indent}base.Deserialize(reader);"); + source.AppendLine(); } // Version @@ -95,6 +98,29 @@ namespace SerializationGenerator ); } + var afterDeserialization = classSymbol + .GetMembers() + .OfType() + .FirstOrDefault( + m => + m.ReturnsVoid && + m.Parameters.Length == 0 && + m.GetAttributes() + .OfType() + .Any( + attr => attr.AttributeClass?.Equals( + compilation.GetTypeByMetadataName(AFTERDESERIALIZATION_ATTRIBUTE), + SymbolEqualityComparer.Default + ) ?? false + ) + ); + + if (afterDeserialization != null) + { + source.AppendLine(); + source.AppendLine($"{indent}Timer.DelayCall({afterDeserialization.Name});"); + } + source.GenerateMethodEnd(); } } diff --git a/Projects/SerializationGenerator/SerializableEntityGeneration/SerializableEntityGeneration.MetadataTypes.cs b/Projects/SerializationGenerator/SerializableEntityGeneration/SerializableEntityGeneration.MetadataTypes.cs index 66038f715..1068cd4fa 100644 --- a/Projects/SerializationGenerator/SerializableEntityGeneration/SerializableEntityGeneration.MetadataTypes.cs +++ b/Projects/SerializationGenerator/SerializableEntityGeneration/SerializableEntityGeneration.MetadataTypes.cs @@ -26,6 +26,7 @@ namespace SerializationGenerator public const string IPADDRESS_CLASS = "System.Net.IPAddress"; public const string KEYVALUEPAIR_STRUCT = "System.Collections.Generic.KeyValuePair"; + public const string AFTERDESERIALIZATION_ATTRIBUTE = "Server.AfterDeserializationAttribute"; public const string SERIALIZABLE_ATTRIBUTE = "Server.SerializableAttribute"; public const string SERIALIZABLE_FIELD_ATTRIBUTE = "Server.SerializableFieldAttribute"; public const string SERIALIZABLE_FIELD_ATTR_ATTRIBUTE = "Server.SerializableFieldAttrAttribute"; diff --git a/Projects/Server/Serialization/AfterDeserialization.cs b/Projects/Server/Serialization/AfterDeserialization.cs new file mode 100644 index 000000000..ee9be83a5 --- /dev/null +++ b/Projects/Server/Serialization/AfterDeserialization.cs @@ -0,0 +1,28 @@ +/************************************************************************* + * ModernUO * + * Copyright 2019-2021 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: AfterDeserialization.cs * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *************************************************************************/ + +using System; + +namespace Server +{ + /// + /// Hints to the source generator that this method should be executed after deserializing the object. + /// Method must have no parameters and return void. + /// + [AttributeUsage(AttributeTargets.Method)] + public class AfterDeserializationAttribute : Attribute + { + } +}