Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of HardheimTimedSave v1.3.0
HardheimTimedSave.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Logging; using HarmonyLib; using UnityEngine; using UnityEngine.Networking; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Hardheim.Timesave")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Hardheim.Timesave")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("3739dcd7-5f69-4a5a-bdde-a190eac212ba")] [assembly: AssemblyFileVersion("1.2.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.2.0.0")] [BepInPlugin("hardheim.timedsave", "Hardheim Timed Save", "1.2.0")] public class TimedSave : BaseUnityPlugin { private sealed class ConfigData { public bool enabled { get; set; } public List<string> saveTimes { get; set; } public string timezone { get; set; } public Announce announce { get; set; } public Combat combatCheck { get; set; } public Backup backup { get; set; } public Restart restart { get; set; } public Webhook webhook { get; set; } public Status status { get; set; } public bool logToConsole { get; set; } } private sealed class Announce { public bool enabled { get; set; } public int secondsBefore { get; set; } public string message { get; set; } } private sealed class Combat { public bool enabled { get; set; } public bool delayIfInCombat { get; set; } public int retrySeconds { get; set; } } private sealed class Backup { public bool enabled { get; set; } public string folder { get; set; } public bool zip { get; set; } public int keepLast { get; set; } public int delaySeconds { get; set; } public List<string> worldSearchPaths { get; set; } public string customWorldPath { get; set; } } private sealed class Restart { public bool enabled { get; set; } public List<string> restartTimes { get; set; } public int secondsBefore { get; set; } public string announceMessage { get; set; } public string finalMessage { get; set; } public bool delayIfInCombat { get; set; } public int retrySeconds { get; set; } public bool saveBeforeRestart { get; set; } public bool backupBeforeRestart { get; set; } public bool kickPlayersBeforeRestart { get; set; } public int kickBeforeSeconds { get; set; } public string kickMessage { get; set; } public int kickDelaySeconds { get; set; } public int shutdownDelaySeconds { get; set; } public int forceExitAfterSeconds { get; set; } public int kickMessageLeadSeconds { get; set; } } private sealed class Webhook { public bool enabled { get; set; } public string url { get; set; } public string username { get; set; } public string avatarUrl { get; set; } public string serverName { get; set; } public bool useEmbeds { get; set; } public bool sendOnSuccess { get; set; } public bool sendOnError { get; set; } public bool sendOnRestart { get; set; } public string successMessage { get; set; } public string errorMessage { get; set; } public string restartMessage { get; set; } public string restartErrorMessage { get; set; } } private sealed class Status { public bool enabled { get; set; } public string message { get; set; } public bool onlyWhenPlayersOnline { get; set; } } private enum WebhookEventType { BackupSuccess, BackupError, Restart, RestartError, Status } [Serializable] private sealed class DiscordWebhookPayload { public string content; public string username; public string avatar_url; public DiscordEmbed[] embeds; } [Serializable] private sealed class DiscordEmbed { public string title; public string description; public int color; public DiscordEmbedField[] fields; public string timestamp; public DiscordEmbedFooter footer; } [Serializable] private sealed class DiscordEmbedField { public string name; public string value; public bool inline; } [Serializable] private sealed class DiscordEmbedFooter { public string text; } [CompilerGenerated] private sealed class <ForceQuitAfterDelay>d__39 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public int seconds; public TimedSave <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ForceQuitAfterDelay>d__39(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds((float)seconds); <>1__state = 1; return true; case 1: <>1__state = -1; Environment.Exit(0); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <HandlePreSaveAnnounce>d__40 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public TimedSave <>4__this; private int <secondsBefore>5__1; private string <announceMessage>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <HandlePreSaveAnnounce>d__40(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <announceMessage>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Expected O, but got Unknown int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; } else { <>1__state = -1; if (<>4__this.config.announce == null || !<>4__this.config.announce.enabled) { goto IL_0120; } <secondsBefore>5__1 = Mathf.Max(0, <>4__this.config.announce.secondsBefore); <announceMessage>5__2 = (string.IsNullOrWhiteSpace(<>4__this.config.announce.message) ? "Szerver mentés {seconds} mp múlva!" : <>4__this.config.announce.message); <announceMessage>5__2 = <announceMessage>5__2.Replace("{seconds}", <secondsBefore>5__1.ToString()); <>4__this.SendCenterMessage(<announceMessage>5__2); if (<secondsBefore>5__1 > 0) { <>2__current = (object)new WaitForSeconds((float)<secondsBefore>5__1); <>1__state = 1; return true; } } <announceMessage>5__2 = null; goto IL_0120; IL_0120: return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <HandleSaveCombatDelay>d__41 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public TimedSave <>4__this; private int <retrySeconds>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <HandleSaveCombatDelay>d__41(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; } else { <>1__state = -1; if (<>4__this.config.combatCheck == null || !<>4__this.config.combatCheck.enabled || !<>4__this.config.combatCheck.delayIfInCombat) { goto IL_00c0; } <retrySeconds>5__1 = Mathf.Max(1, <>4__this.config.combatCheck.retrySeconds); } if (<>4__this.IsAnyoneInCombat()) { <>2__current = (object)new WaitForSeconds((float)<retrySeconds>5__1); <>1__state = 1; return true; } goto IL_00c0; IL_00c0: return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <PostWebhook>d__63 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public WebhookEventType eventType; public string serverName; public string worldName; public string backupFolder; public string pathValue; public string error; public int playerCount; public string uptime; public TimedSave <>4__this; private DiscordWebhookPayload <payload>5__1; private string <template>5__2; private string <message>5__3; private string <json>5__4; private byte[] <bodyRaw>5__5; private UnityWebRequest <request>5__6; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PostWebhook>d__63(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <payload>5__1 = null; <template>5__2 = null; <message>5__3 = null; <json>5__4 = null; <bodyRaw>5__5 = null; <request>5__6 = null; <>1__state = -2; } private bool MoveNext() { //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Expected O, but got Unknown //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Expected O, but got Unknown //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <template>5__2 = <>4__this.GetTemplateForEvent(eventType); <message>5__3 = <>4__this.BuildWebhookMessage(<template>5__2, serverName, worldName, backupFolder, pathValue, error, playerCount, uptime); if (<>4__this.config.webhook.useEmbeds && eventType != WebhookEventType.Status) { <payload>5__1 = <>4__this.BuildEmbedPayload(eventType, serverName, worldName, backupFolder, pathValue, error, playerCount, uptime); } else { <payload>5__1 = new DiscordWebhookPayload { content = <message>5__3, username = (string.IsNullOrWhiteSpace(<>4__this.config.webhook.username) ? "Hardheim Timed Save" : <>4__this.config.webhook.username), avatar_url = (string.IsNullOrWhiteSpace(<>4__this.config.webhook.avatarUrl) ? null : <>4__this.config.webhook.avatarUrl), embeds = null }; } <json>5__4 = JsonUtility.ToJson((object)<payload>5__1); <bodyRaw>5__5 = Encoding.UTF8.GetBytes(<json>5__4); <request>5__6 = new UnityWebRequest(<>4__this.config.webhook.url, "POST"); <>1__state = -3; <request>5__6.uploadHandler = (UploadHandler)new UploadHandlerRaw(<bodyRaw>5__5); <request>5__6.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); <request>5__6.SetRequestHeader("Content-Type", "application/json"); <>2__current = <request>5__6.SendWebRequest(); <>1__state = 1; return true; case 1: <>1__state = -3; <>m__Finally1(); <request>5__6 = null; return false; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<request>5__6 != null) { ((IDisposable)<request>5__6).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <RestartRoutine>d__31 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string triggerSource; public TimedSave <>4__this; private string <serverName>5__1; private string <worldName>5__2; private int <secondsBefore>5__3; private string <announceMessage>5__4; private int <kickDelaySeconds>5__5; private int <shutdownDelay>5__6; private bool <useKickWindow>5__7; private int <firstWait>5__8; private float <remainingKickWindow>5__9; private int <retrySeconds>5__10; private int <backupDelay>5__11; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RestartRoutine>d__31(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 7u) { try { } finally { <>m__Finally1(); } } <serverName>5__1 = null; <worldName>5__2 = null; <announceMessage>5__4 = null; <>1__state = -2; } private bool MoveNext() { //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Expected O, but got Unknown //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Expected O, but got Unknown //IL_03e4: Unknown result type (might be due to invalid IL or missing references) //IL_03ee: Expected O, but got Unknown //IL_05de: Unknown result type (might be due to invalid IL or missing references) //IL_05e8: Expected O, but got Unknown //IL_0584: Unknown result type (might be due to invalid IL or missing references) //IL_058e: Expected O, but got Unknown //IL_04d7: Unknown result type (might be due to invalid IL or missing references) //IL_04e1: Expected O, but got Unknown //IL_0356: Unknown result type (might be due to invalid IL or missing references) //IL_0360: Expected O, but got Unknown //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (<>4__this.restartInProgress || <>4__this.saveInProgress) { return false; } <>4__this.restartInProgress = true; <serverName>5__1 = <>4__this.GetDisplayServerName(); <worldName>5__2 = <>4__this.GetSafeWorldName(); <>1__state = -3; <secondsBefore>5__3 = Mathf.Max(0, <>4__this.config.restart.secondsBefore); <announceMessage>5__4 = (string.IsNullOrWhiteSpace(<>4__this.config.restart.announceMessage) ? "Szerver restart {seconds} mp múlva!" : <>4__this.config.restart.announceMessage); <announceMessage>5__4 = <announceMessage>5__4.Replace("{seconds}", <secondsBefore>5__3.ToString()); if (<secondsBefore>5__3 > 0) { <>4__this.SendCenterMessage(<announceMessage>5__4); <>4__this.LogInfo("Restart figyelmeztetés kiküldve: " + <announceMessage>5__4); <useKickWindow>5__7 = <>4__this.config.restart.kickPlayersBeforeRestart && <secondsBefore>5__3 >= <>4__this.config.restart.kickBeforeSeconds && <>4__this.config.restart.kickBeforeSeconds > 0; if (<useKickWindow>5__7) { <firstWait>5__8 = <secondsBefore>5__3 - <>4__this.config.restart.kickBeforeSeconds; if (<firstWait>5__8 > 0) { <>2__current = (object)new WaitForSeconds((float)<firstWait>5__8); <>1__state = 1; return true; } goto IL_0249; } <>2__current = (object)new WaitForSeconds((float)<secondsBefore>5__3); <>1__state = 4; return true; } goto IL_0378; case 1: <>1__state = -3; goto IL_0249; case 2: <>1__state = -3; <>4__this.KickAllPlayersBeforeRestart(); <remainingKickWindow>5__9 = (float)<>4__this.config.restart.kickBeforeSeconds - 2f; if (<remainingKickWindow>5__9 > 0f) { <>2__current = (object)new WaitForSeconds(<remainingKickWindow>5__9); <>1__state = 3; return true; } goto IL_0378; case 3: <>1__state = -3; goto IL_0378; case 4: <>1__state = -3; goto IL_0378; case 5: <>1__state = -3; goto IL_0405; case 6: <>1__state = -3; goto IL_04f8; case 7: <>1__state = -3; goto IL_05a5; case 8: { <>1__state = -3; break; } IL_0405: if (<>4__this.IsAnyoneInCombat()) { <>4__this.LogInfo($"Restart halasztva, mert legalább egy játékos harcban van. Újrapróbálás {<retrySeconds>5__10} mp múlva."); <>2__current = (object)new WaitForSeconds((float)<retrySeconds>5__10); <>1__state = 5; return true; } goto IL_0417; IL_0417: ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.SendWebhookRestart(<serverName>5__1, <worldName>5__2)); if (<>4__this.config.restart.saveBeforeRestart) { <>4__this.SaveWorld(); } if (<>4__this.config.restart.backupBeforeRestart) { <backupDelay>5__11 = ((<>4__this.config != null && <>4__this.config.backup != null) ? <>4__this.config.backup.delaySeconds : 2); if (<backupDelay>5__11 > 0) { <>2__current = (object)new WaitForSeconds((float)<backupDelay>5__11); <>1__state = 6; return true; } goto IL_04f8; } goto IL_0505; IL_05a5: <shutdownDelay>5__6 = Mathf.Max(0, <>4__this.config.restart.shutdownDelaySeconds); if (<shutdownDelay>5__6 > 0) { <>2__current = (object)new WaitForSeconds((float)<shutdownDelay>5__6); <>1__state = 8; return true; } break; IL_0249: if (!string.IsNullOrWhiteSpace(<>4__this.config.restart.kickMessage)) { <>4__this.SendCenterMessage(<>4__this.config.restart.kickMessage); <>4__this.LogInfo("Kick előtti üzenet kiküldve: " + <>4__this.config.restart.kickMessage); } <>2__current = (object)new WaitForSeconds(2f); <>1__state = 2; return true; IL_0378: if (<>4__this.config.restart.delayIfInCombat) { <retrySeconds>5__10 = Mathf.Max(1, <>4__this.config.restart.retrySeconds); goto IL_0405; } goto IL_0417; IL_04f8: <>4__this.DoBackup(); goto IL_0505; IL_0505: if (!string.IsNullOrWhiteSpace(<>4__this.config.restart.finalMessage)) { <>4__this.SendCenterMessage(<>4__this.config.restart.finalMessage); } <kickDelaySeconds>5__5 = Mathf.Max(0, <>4__this.config.restart.kickDelaySeconds); if (<kickDelaySeconds>5__5 > 0) { <>2__current = (object)new WaitForSeconds((float)<kickDelaySeconds>5__5); <>1__state = 7; return true; } goto IL_05a5; } ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.ForceQuitAfterDelay(Mathf.Max(1, <>4__this.config.restart.forceExitAfterSeconds))); Application.Quit(); <announceMessage>5__4 = null; <>m__Finally1(); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; <>4__this.restartInProgress = false; } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <SaveRoutine>d__30 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string triggerSource; public TimedSave <>4__this; private int <backupDelay>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SaveRoutine>d__30(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 2u) { try { } finally { <>m__Finally1(); } } <>1__state = -2; } private bool MoveNext() { //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (<>4__this.saveInProgress || <>4__this.restartInProgress) { return false; } <>4__this.saveInProgress = true; <>1__state = -3; <>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.HandlePreSaveAnnounce()); <>1__state = 1; return true; case 1: <>1__state = -3; <>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.HandleSaveCombatDelay()); <>1__state = 2; return true; case 2: <>1__state = -3; <>4__this.SaveWorld(); <backupDelay>5__1 = ((<>4__this.config != null && <>4__this.config.backup != null) ? <>4__this.config.backup.delaySeconds : 2); if (<backupDelay>5__1 > 0) { <>2__current = (object)new WaitForSeconds((float)<backupDelay>5__1); <>1__state = 3; return true; } break; case 3: <>1__state = -3; break; } <>4__this.DoBackup(); <>m__Finally1(); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; <>4__this.saveInProgress = false; } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <SendOnlineWebhookOnceAfterStartup>d__38 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public TimedSave <>4__this; private int <playerCount>5__1; private string <serverName>5__2; private string <worldName>5__3; private string <uptime>5__4; private Exception <ex>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SendOnlineWebhookOnceAfterStartup>d__38(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <serverName>5__2 = null; <worldName>5__3 = null; <uptime>5__4 = null; <ex>5__5 = null; <>1__state = -2; } private bool MoveNext() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(30f); <>1__state = 1; return true; case 1: <>1__state = -1; if (!<>4__this.IsWebhookEnabledForStatus()) { return false; } <playerCount>5__1 = 0; <serverName>5__2 = "Hardheim"; <worldName>5__3 = "unknownworld"; <uptime>5__4 = "-"; try { <playerCount>5__1 = <>4__this.GetOnlinePlayerCount(); if (<>4__this.config.status.onlyWhenPlayersOnline && <playerCount>5__1 <= 0) { <>4__this.LogInfo("Online webhook kihagyva, mert nincs online játékos."); return false; } <serverName>5__2 = <>4__this.GetDisplayServerName(); <worldName>5__3 = <>4__this.GetSafeWorldName(); <uptime>5__4 = <>4__this.GetFormattedUptime(); } catch (Exception ex) { <ex>5__5 = ex; <>4__this.LogError("Egyszeri online webhook előkészítési hiba: " + <ex>5__5.Message); return false; } <>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.PostWebhook(WebhookEventType.Status, <serverName>5__2, <worldName>5__3, "-", "-", string.Empty, <playerCount>5__1, <uptime>5__4)); <>1__state = 2; return true; case 2: <>1__state = -1; <>4__this.LogInfo("Egyszeri online webhook elküldve."); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <SendWebhookError>d__54 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string serverName; public string worldName; public string backupFolder; public string error; public TimedSave <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SendWebhookError>d__54(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (!<>4__this.IsWebhookEnabledForError()) { return false; } <>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.PostWebhook(WebhookEventType.BackupError, serverName, worldName, backupFolder, string.Empty, error, <>4__this.GetOnlinePlayerCount(), <>4__this.GetFormattedUptime())); <>1__state = 1; return true; case 1: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <SendWebhookRestart>d__55 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string serverName; public string worldName; public TimedSave <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SendWebhookRestart>d__55(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (!<>4__this.IsWebhookEnabledForRestart()) { return false; } <>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.PostWebhook(WebhookEventType.Restart, serverName, worldName, "-", "-", string.Empty, <>4__this.GetOnlinePlayerCount(), <>4__this.GetFormattedUptime())); <>1__state = 1; return true; case 1: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <SendWebhookRestartError>d__56 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string serverName; public string worldName; public string error; public TimedSave <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SendWebhookRestartError>d__56(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (!<>4__this.IsWebhookEnabledForRestart()) { return false; } <>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.PostWebhook(WebhookEventType.RestartError, serverName, worldName, "-", "-", error, <>4__this.GetOnlinePlayerCount(), <>4__this.GetFormattedUptime())); <>1__state = 1; return true; case 1: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <SendWebhookSuccess>d__53 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string serverName; public string worldName; public string backupFolder; public string pathValue; public TimedSave <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SendWebhookSuccess>d__53(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (!<>4__this.IsWebhookEnabledForSuccess()) { return false; } <>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.PostWebhook(WebhookEventType.BackupSuccess, serverName, worldName, backupFolder, pathValue, string.Empty, <>4__this.GetOnlinePlayerCount(), <>4__this.GetFormattedUptime())); <>1__state = 1; return true; case 1: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static ManualLogSource Log; private ConfigData config; private readonly HashSet<string> executedToday = new HashSet<string>(); private readonly HashSet<string> restartedToday = new HashSet<string>(); private DateTime lastDay; private bool saveInProgress; private bool restartInProgress; private Harmony harmony; private DateTime pluginStartUtc; public static TimedSave Instance { get; private set; } private void Awake() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; pluginStartUtc = DateTime.UtcNow; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[HardheimTimedSave] Mod betöltve."); LoadConfig(); harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); harmony.PatchAll(); ((MonoBehaviour)this).InvokeRepeating("CheckTime", 5f, 30f); if (config != null && config.status != null && config.status.enabled) { ((MonoBehaviour)this).StartCoroutine(SendOnlineWebhookOnceAfterStartup()); LogInfo("Egyszeri online webhook indítása ütemezve."); } } private void OnDestroy() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } } private void LoadConfig() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown string path = Path.Combine(Paths.ConfigPath, ((BaseUnityPlugin)this).Info.Metadata.GUID + ".yml"); if (!File.Exists(path)) { string contents = "# ============================================\r\n# Hardheim Timed Save\r\n# ============================================\r\n# Automatikus szerver mentés és időzített restart\r\n# ============================================\r\n\r\nenabled: true\r\n\r\nsaveTimes:\r\n - \"23:55\"\r\n\r\ntimezone: \"Europe/Budapest\"\r\n\r\nannounce:\r\n enabled: true\r\n secondsBefore: 10\r\n message: \"Szerver mentés {seconds} mp múlva!\"\r\n\r\ncombatCheck:\r\n enabled: true\r\n delayIfInCombat: true\r\n retrySeconds: 30\r\n\r\nbackup:\r\n enabled: true\r\n folder: \"backups\"\r\n zip: true\r\n keepLast: 3\r\n delaySeconds: 2\r\n customWorldPath: \"\"\r\n worldSearchPaths:\r\n - \"worlds_local\"\r\n - \"worlds_local/worlds\"\r\n\r\nrestart:\r\n enabled: false\r\n restartTimes:\r\n - \"04:00\"\r\n secondsBefore: 60\r\n announceMessage: \"Szerver restart {seconds} mp múlva!\"\r\n finalMessage: \"Szerver restart indul, hamarosan visszatérünk!\"\r\n delayIfInCombat: true\r\n retrySeconds: 30\r\n saveBeforeRestart: true\r\n backupBeforeRestart: true\r\n kickPlayersBeforeRestart: true\r\n kickBeforeSeconds: 30\r\n kickMessage: \"Játékosok kirúgása a szerverről, újraindítás miatt\"\r\n kickDelaySeconds: 2\r\n shutdownDelaySeconds: 5\r\n forceExitAfterSeconds: 15\r\n\r\nwebhook:\r\n enabled: false\r\n url: \"\"\r\n username: \"Hardheim Timed Save\"\r\n avatarUrl: \"\"\r\n serverName: \"Hardheim\"\r\n useEmbeds: true\r\n sendOnSuccess: true\r\n sendOnError: true\r\n sendOnRestart: true\r\n successMessage: \"✅ Backup elkészült | Szerver: {server} | Világ: {world} | Mappa: {folder} | Fájl: {path} | Megtartott mentések: {keepLast} | Idő: {time}\"\r\n errorMessage: \"❌ Backup hiba | Szerver: {server} | Világ: {world} | Hiba: {error} | Idő: {time}\"\r\n restartMessage: \"\ud83d\udd01 Szerver restart indul | Szerver: {server} | Világ: {world} | Játékosok: {players} | Idő: {time}\"\r\n restartErrorMessage: \"❌ Restart hiba | Szerver: {server} | Világ: {world} | Hiba: {error} | Idő: {time}\"\r\n\r\nstatus:\r\n enabled: false\r\n onlyWhenPlayersOnline: false\r\n message: \"\ud83d\udfe2 Szerver online | Szerver: {server} | Világ: {world} | Játékosok: {players} | Uptime: {uptime} | Idő: {time}\"\r\n\r\nlogToConsole: true\r\n"; File.WriteAllText(path, contents); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[HardheimTimedSave] Alapértelmezett config létrehozva."); } IDeserializer val = ((BuilderSkeleton<DeserializerBuilder>)new DeserializerBuilder()).WithNamingConvention(CamelCaseNamingConvention.Instance).IgnoreUnmatchedProperties().Build(); config = val.Deserialize<ConfigData>(File.ReadAllText(path)); if (config == null) { config = new ConfigData(); } if (config.saveTimes == null || config.saveTimes.Count == 0) { config.saveTimes = new List<string> { "23:55" }; } if (string.IsNullOrWhiteSpace(config.timezone)) { config.timezone = "Europe/Budapest"; } if (config.announce == null) { config.announce = new Announce { enabled = true, secondsBefore = 10, message = "Szerver mentés {seconds} mp múlva!" }; } if (config.combatCheck == null) { config.combatCheck = new Combat { enabled = true, delayIfInCombat = true, retrySeconds = 30 }; } if (config.backup == null) { config.backup = new Backup { enabled = true, folder = "backups", zip = true, keepLast = 3, delaySeconds = 2, worldSearchPaths = new List<string> { "worlds_local", "worlds_local/worlds" }, customWorldPath = "" }; } if (config.backup.worldSearchPaths == null || config.backup.worldSearchPaths.Count == 0) { config.backup.worldSearchPaths = new List<string> { "worlds_local", "worlds_local/worlds" }; } if (config.backup.customWorldPath == null) { config.backup.customWorldPath = ""; } if (config.restart == null) { config.restart = new Restart { enabled = false, restartTimes = new List<string> { "04:00" }, secondsBefore = 60, announceMessage = "Szerver restart {seconds} mp múlva!", finalMessage = "Szerver restart indul, hamarosan visszatérünk!", delayIfInCombat = true, retrySeconds = 30, saveBeforeRestart = true, backupBeforeRestart = true, kickPlayersBeforeRestart = true, kickBeforeSeconds = 30, kickMessage = "Játékosok kirúgása a szerverről, újraindítás miatt", kickMessageLeadSeconds = 2, kickDelaySeconds = 2, shutdownDelaySeconds = 5, forceExitAfterSeconds = 15 }; } if (config.restart.restartTimes == null || config.restart.restartTimes.Count == 0) { config.restart.restartTimes = new List<string> { "04:00" }; } if (config.webhook == null) { config.webhook = new Webhook { enabled = false, url = string.Empty, username = "Hardheim Timed Save", avatarUrl = string.Empty, serverName = "Hardheim", useEmbeds = true, sendOnSuccess = true, sendOnError = true, sendOnRestart = true, successMessage = "✅ Backup elkészült | Szerver: {server} | Világ: {world} | Mappa: {folder} | Fájl: {path} | Megtartott mentések: {keepLast} | Idő: {time}", errorMessage = "❌ Backup hiba | Szerver: {server} | Világ: {world} | Hiba: {error} | Idő: {time}", restartMessage = "\ud83d\udd01 Szerver restart indul | Szerver: {server} | Világ: {world} | Játékosok: {players} | Idő: {time}", restartErrorMessage = "❌ Restart hiba | Szerver: {server} | Világ: {world} | Hiba: {error} | Idő: {time}" }; } if (config.status == null) { config.status = new Status { enabled = false, onlyWhenPlayersOnline = false, message = "\ud83d\udfe2 Szerver online | Szerver: {server} | Világ: {world} | Játékosok: {players} | Uptime: {uptime} | Idő: {time}" }; } if (string.IsNullOrWhiteSpace(config.backup.folder)) { config.backup.folder = "backups"; } if (config.backup.keepLast < 3) { config.backup.keepLast = 3; LogWarning("A keepLast túl alacsony volt, 3-ra állítva."); } else if (config.backup.keepLast > 10) { config.backup.keepLast = 10; LogWarning("A keepLast túl magas volt, 10-re állítva."); } if (config.backup.delaySeconds < 0) { config.backup.delaySeconds = 2; } if (config.restart.secondsBefore < 0) { config.restart.secondsBefore = 60; } if (config.restart.retrySeconds < 1) { config.restart.retrySeconds = 30; } if (config.restart.kickBeforeSeconds < 0) { config.restart.kickBeforeSeconds = 30; } if (config.restart.kickDelaySeconds < 0) { config.restart.kickDelaySeconds = 2; } if (config.restart.shutdownDelaySeconds < 0) { config.restart.shutdownDelaySeconds = 5; } if (config.restart.forceExitAfterSeconds < 1) { config.restart.forceExitAfterSeconds = 15; } if (string.IsNullOrWhiteSpace(config.restart.kickMessage)) { config.restart.kickMessage = "Játékosok kirúgása a szerverről, újraindítás miatt"; } if (string.IsNullOrWhiteSpace(config.webhook.username)) { config.webhook.username = "Hardheim Timed Save"; } if (string.IsNullOrWhiteSpace(config.webhook.serverName)) { config.webhook.serverName = "Hardheim"; } if (string.IsNullOrWhiteSpace(config.status.message)) { config.status.message = "\ud83d\udfe2 Szerver online | Szerver: {server} | Világ: {world} | Játékosok: {players} | Uptime: {uptime} | Idő: {time}"; } LogInfo("Config betöltve."); } private void CheckTime() { if (config == null || !config.enabled || saveInProgress || restartInProgress) { return; } DateTime time = GetTime(); if (time.Date != lastDay.Date) { executedToday.Clear(); restartedToday.Clear(); lastDay = time.Date; LogInfo("Új nap kezdődött, a napi mentési és restart állapotok törölve lettek."); } string text = time.ToString("HH:mm"); foreach (string saveTime in config.saveTimes) { if (text == saveTime && !executedToday.Contains(saveTime)) { executedToday.Add(saveTime); ((MonoBehaviour)this).StartCoroutine(SaveRoutine(saveTime)); return; } } if (config.restart == null || !config.restart.enabled) { return; } foreach (string restartTime in config.restart.restartTimes) { if (text == restartTime && !restartedToday.Contains(restartTime)) { restartedToday.Add(restartTime); ((MonoBehaviour)this).StartCoroutine(RestartRoutine(restartTime)); break; } } } private DateTime GetTime() { string text = ((config != null && !string.IsNullOrWhiteSpace(config.timezone)) ? config.timezone.Trim() : "Europe/Budapest"); string text2 = text.ToUpperInvariant(); try { switch (text2) { case "UTC": return DateTime.UtcNow; case "CET": case "CEST": case "EUROPE/BUDAPEST": return TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? TimeZoneInfo.FindSystemTimeZoneById("Central Europe Standard Time") : TimeZoneInfo.FindSystemTimeZoneById("Europe/Budapest")); default: { TimeZoneInfo destinationTimeZone = TimeZoneInfo.FindSystemTimeZoneById(text); return TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, destinationTimeZone); } } } catch { return DateTime.Now; } } [IteratorStateMachine(typeof(<SaveRoutine>d__30))] private IEnumerator SaveRoutine(string triggerSource) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SaveRoutine>d__30(0) { <>4__this = this, triggerSource = triggerSource }; } [IteratorStateMachine(typeof(<RestartRoutine>d__31))] private IEnumerator RestartRoutine(string triggerSource) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RestartRoutine>d__31(0) { <>4__this = this, triggerSource = triggerSource }; } private void KickAllPlayersBeforeRestart() { if ((Object)(object)ZNet.instance == (Object)null) { LogWarning("Kick kihagyva, mert a ZNet.instance nem elérhető."); return; } try { List<object> connectedPeerObjects = GetConnectedPeerObjects(); if (connectedPeerObjects.Count == 0) { LogInfo("Nincs kickelendő játékos."); return; } LogInfo($"Restart előtti játékosbontás indul. Érintett peer-ek: {connectedPeerObjects.Count}"); foreach (object item in connectedPeerObjects) { if (item == null) { continue; } try { string peerPlayerName = GetPeerPlayerName(item); LogInfo("Játékos bontása restart előtt: " + peerPlayerName); object memberValue = GetMemberValue(item, "m_rpc"); if (memberValue != null) { InvokeRpcError(memberValue); } if (!DisconnectPeer(item)) { LogWarning("A peer bontása nem sikerült reflektíven. Név: " + peerPlayerName); } } catch (Exception ex) { LogError("Nem sikerült egy játékost bontani: " + ex.Message); } } } catch (Exception ex2) { LogError("KickAllPlayersBeforeRestart hiba: " + ex2.Message); } } private List<object> GetConnectedPeerObjects() { List<object> list = new List<object>(); object instance = ZNet.instance; if (instance == null) { return list; } string[] array = new string[3] { "m_peers", "m_peerConnections", "m_connections" }; string[] array2 = array; foreach (string memberName in array2) { object memberValue = GetMemberValue(instance, memberName); if (!(memberValue is IEnumerable enumerable)) { continue; } foreach (object item in enumerable) { if (item != null) { list.Add(item); } } if (list.Count > 0) { return list; } } return list; } private string GetPeerPlayerName(object peer) { object memberValue = GetMemberValue(peer, "m_playerName"); if (memberValue is string text && !string.IsNullOrWhiteSpace(text)) { return text; } return "unknownplayer"; } private bool DisconnectPeer(object peer) { object instance = ZNet.instance; if (instance == null || peer == null) { return false; } Type type = instance.GetType(); Type type2 = peer.GetType(); MethodInfo method = type.GetMethod("Disconnect", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { type2 }, null); if (method != null) { method.Invoke(instance, new object[1] { peer }); return true; } object memberValue = GetMemberValue(peer, "m_rpc"); if (memberValue != null) { Type type3 = memberValue.GetType(); MethodInfo method2 = type.GetMethod("Disconnect", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { type3 }, null); if (method2 != null) { method2.Invoke(instance, new object[1] { memberValue }); return true; } MethodInfo method3 = type3.GetMethod("Close", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method3 != null) { method3.Invoke(memberValue, null); return true; } } return false; } private void InvokeRpcError(object rpc) { if (rpc == null) { return; } Type type = rpc.GetType(); MethodInfo methodInfo = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == "Invoke" && m.GetParameters().Length == 2); if (methodInfo == null) { return; } try { methodInfo.Invoke(rpc, new object[2] { "Error", 3 }); } catch { try { methodInfo.Invoke(rpc, new object[2] { "Error", new object[1] { 3 } }); } catch { } } } private object GetMemberValue(object instance, string memberName) { if (instance == null || string.IsNullOrWhiteSpace(memberName)) { return null; } Type type = instance.GetType(); FieldInfo field = type.GetField(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field.GetValue(instance); } PropertyInfo property = type.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { return property.GetValue(instance, null); } return null; } [IteratorStateMachine(typeof(<SendOnlineWebhookOnceAfterStartup>d__38))] private IEnumerator SendOnlineWebhookOnceAfterStartup() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SendOnlineWebhookOnceAfterStartup>d__38(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<ForceQuitAfterDelay>d__39))] private IEnumerator ForceQuitAfterDelay(int seconds) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ForceQuitAfterDelay>d__39(0) { <>4__this = this, seconds = seconds }; } [IteratorStateMachine(typeof(<HandlePreSaveAnnounce>d__40))] private IEnumerator HandlePreSaveAnnounce() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <HandlePreSaveAnnounce>d__40(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<HandleSaveCombatDelay>d__41))] private IEnumerator HandleSaveCombatDelay() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <HandleSaveCombatDelay>d__41(0) { <>4__this = this }; } private bool IsAnyoneInCombat() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown foreach (Player allPlayer in Player.GetAllPlayers()) { if ((Object)allPlayer != (Object)null && (((Character)allPlayer).InAttack() || ((Character)allPlayer).IsBlocking())) { return true; } } return false; } private void SaveWorld() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown if ((Object)ZNet.instance == (Object)null) { LogWarning("A világmentés nem futott le, mert a ZNet.instance nem elérhető."); } else { ZNet.instance.Save(false, false, false); } } private void DoBackup() { string safeWorldName = GetSafeWorldName(); string displayServerName = GetDisplayServerName(); string text = string.Empty; if (config == null || config.backup == null || !config.backup.enabled) { return; } try { string text2 = ResolveWorldsFolder(); string path = Path.Combine(Paths.BepInExRootPath, config.backup.folder); text = Path.Combine(path, safeWorldName); Directory.CreateDirectory(text); List<string> worldFiles = GetWorldFiles(text2, safeWorldName); if (worldFiles.Count == 0) { throw new FileNotFoundException("Nem találhatók az aktuális világhoz tartozó fájlok. Világ: " + safeWorldName + " | Mappa: " + text2); } string text3 = "backup_" + safeWorldName + "_"; string text4 = GetTime().ToString("yyyyMMdd_HHmmss"); if (config.backup.zip) { string text5 = Path.Combine(text, text3 + text4 + ".zip"); CreateWorldZip(text5, worldFiles); CleanupOldBackups(text, text3); ((MonoBehaviour)this).StartCoroutine(SendWebhookSuccess(displayServerName, safeWorldName, text, text5)); return; } string text6 = Path.Combine(text, text3 + text4); Directory.CreateDirectory(text6); foreach (string item in worldFiles) { string destFileName = Path.Combine(text6, Path.GetFileName(item)); File.Copy(item, destFileName, overwrite: true); } CleanupOldBackupFolders(text, text3); ((MonoBehaviour)this).StartCoroutine(SendWebhookSuccess(displayServerName, safeWorldName, text, text6)); } catch (Exception ex) { ((MonoBehaviour)this).StartCoroutine(SendWebhookError(displayServerName, safeWorldName, text, ex.Message)); } } private string ResolveWorldsFolder() { List<string> list = new List<string>(); if (!string.IsNullOrWhiteSpace((config != null && config.backup != null) ? config.backup.customWorldPath : null)) { string text = config.backup.customWorldPath.Trim(); string text2 = (Path.IsPathRooted(text) ? text : Path.Combine(Application.persistentDataPath, text)); list.Add(text2); if (Directory.Exists(text2)) { return text2; } } List<string> list2 = ((config != null && config.backup != null) ? config.backup.worldSearchPaths : null); if (list2 == null || list2.Count == 0) { list2 = new List<string> { "worlds_local", "worlds_local/worlds" }; } foreach (string item in list2) { if (!string.IsNullOrWhiteSpace(item)) { string path = item.Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar); string text3 = Path.Combine(Application.persistentDataPath, path); list.Add(text3); if (Directory.Exists(text3)) { return text3; } } } throw new DirectoryNotFoundException("Nem található a világ mappa. Ellenőrzött: " + string.Join(" | ", list)); } private void CreateWorldZip(string zipPath, List<string> sourceFiles) { if (File.Exists(zipPath)) { File.Delete(zipPath); } using FileStream stream = new FileStream(zipPath, FileMode.CreateNew); using ZipArchive destination = new ZipArchive(stream, ZipArchiveMode.Create); foreach (string sourceFile in sourceFiles) { string fileName = Path.GetFileName(sourceFile); destination.CreateEntryFromFile(sourceFile, fileName, CompressionLevel.Optimal); } } private List<string> GetWorldFiles(string worldsFolder, string worldName) { List<string> list = new List<string>(); if (string.IsNullOrWhiteSpace(worldsFolder) || !Directory.Exists(worldsFolder)) { return list; } string[] array = new string[2] { worldName + ".db", worldName + ".fwl" }; string[] array2 = array; foreach (string searchPattern in array2) { try { list.AddRange(Directory.GetFiles(worldsFolder, searchPattern, SearchOption.TopDirectoryOnly)); } catch { } } return (from filePath in list.Where(File.Exists).Distinct<string>(StringComparer.OrdinalIgnoreCase) orderby filePath select filePath).ToList(); } private string GetSafeWorldName() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown string value = "unknownworld"; try { if ((Object)ZNet.instance != (Object)null) { string worldName = ZNet.instance.GetWorldName(); if (!string.IsNullOrWhiteSpace(worldName)) { value = worldName.Trim(); } } } catch { } return SanitizeFileName(value, "unknownworld"); } private string GetDisplayServerName() { if (config == null || config.webhook == null || string.IsNullOrWhiteSpace(config.webhook.serverName)) { return "Hardheim"; } return config.webhook.serverName.Trim(); } private string SanitizeFileName(string value, string fallback) { string text = (string.IsNullOrWhiteSpace(value) ? fallback : value.Trim()); char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); foreach (char oldChar in invalidFileNameChars) { text = text.Replace(oldChar, '_'); } text = text.Replace(' ', '_'); if (string.IsNullOrWhiteSpace(text)) { text = fallback; } return text; } private void CleanupOldBackups(string backupFolder, string filePrefix) { try { List<FileInfo> list = (from file in new DirectoryInfo(backupFolder).GetFiles(filePrefix + "*.zip") orderby file.CreationTimeUtc descending select file).ToList(); int keepLast = config.backup.keepLast; if (list.Count <= keepLast) { return; } foreach (FileInfo item in list.Skip(keepLast)) { try { item.Delete(); } catch { } } } catch { } } private void CleanupOldBackupFolders(string backupFolder, string folderPrefix) { try { List<DirectoryInfo> list = (from directory in new DirectoryInfo(backupFolder).GetDirectories(folderPrefix + "*") orderby directory.CreationTimeUtc descending select directory).ToList(); int keepLast = config.backup.keepLast; if (list.Count <= keepLast) { return; } foreach (DirectoryInfo item in list.Skip(keepLast)) { try { item.Delete(recursive: true); } catch { } } } catch { } } [IteratorStateMachine(typeof(<SendWebhookSuccess>d__53))] private IEnumerator SendWebhookSuccess(string serverName, string worldName, string backupFolder, string pathValue) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SendWebhookSuccess>d__53(0) { <>4__this = this, serverName = serverName, worldName = worldName, backupFolder = backupFolder, pathValue = pathValue }; } [IteratorStateMachine(typeof(<SendWebhookError>d__54))] private IEnumerator SendWebhookError(string serverName, string worldName, string backupFolder, string error) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SendWebhookError>d__54(0) { <>4__this = this, serverName = serverName, worldName = worldName, backupFolder = backupFolder, error = error }; } [IteratorStateMachine(typeof(<SendWebhookRestart>d__55))] private IEnumerator SendWebhookRestart(string serverName, string worldName) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SendWebhookRestart>d__55(0) { <>4__this = this, serverName = serverName, worldName = worldName }; } [IteratorStateMachine(typeof(<SendWebhookRestartError>d__56))] private IEnumerator SendWebhookRestartError(string serverName, string worldName, string error) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SendWebhookRestartError>d__56(0) { <>4__this = this, serverName = serverName, worldName = worldName, error = error }; } private bool IsWebhookEnabledForSuccess() { return config != null && config.webhook != null && config.webhook.enabled && config.webhook.sendOnSuccess && !string.IsNullOrWhiteSpace(config.webhook.url); } private bool IsWebhookEnabledForError() { return config != null && config.webhook != null && config.webhook.enabled && config.webhook.sendOnError && !string.IsNullOrWhiteSpace(config.webhook.url); } private bool IsWebhookEnabledForRestart() { return config != null && config.webhook != null && config.webhook.enabled && config.webhook.sendOnRestart && !string.IsNullOrWhiteSpace(config.webhook.url); } private bool IsWebhookEnabledForStatus() { return config != null && config.webhook != null && config.webhook.enabled && config.status != null && config.status.enabled && !string.IsNullOrWhiteSpace(config.webhook.url); } private string BuildWebhookMessage(string template, string serverName, string worldName, string backupFolder, string pathValue, string error, int playerCount, string uptime) { string text = (string.IsNullOrWhiteSpace(template) ? "Hardheim Timed Save webhook üzenet" : template); return text.Replace("{server}", string.IsNullOrWhiteSpace(serverName) ? "unknownserver" : serverName).Replace("{world}", string.IsNullOrWhiteSpace(worldName) ? "unknownworld" : worldName).Replace("{folder}", string.IsNullOrWhiteSpace(backupFolder) ? "-" : backupFolder) .Replace("{path}", string.IsNullOrWhiteSpace(pathValue) ? "-" : pathValue) .Replace("{keepLast}", config.backup.keepLast.ToString()) .Replace("{time}", GetTime().ToString("yyyy-MM-dd HH:mm:ss")) .Replace("{error}", string.IsNullOrWhiteSpace(error) ? "-" : error) .Replace("{players}", playerCount.ToString()) .Replace("{uptime}", string.IsNullOrWhiteSpace(uptime) ? "-" : uptime); } private string GetTemplateForEvent(WebhookEventType eventType) { return eventType switch { WebhookEventType.BackupSuccess => config.webhook.successMessage, WebhookEventType.BackupError => config.webhook.errorMessage, WebhookEventType.Restart => config.webhook.restartMessage, WebhookEventType.RestartError => config.webhook.restartErrorMessage, WebhookEventType.Status => config.status.message, _ => "Hardheim Timed Save webhook üzenet", }; } [IteratorStateMachine(typeof(<PostWebhook>d__63))] private IEnumerator PostWebhook(WebhookEventType eventType, string serverName, string worldName, string backupFolder, string pathValue, string error, int playerCount, string uptime) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PostWebhook>d__63(0) { <>4__this = this, eventType = eventType, serverName = serverName, worldName = worldName, backupFolder = backupFolder, pathValue = pathValue, error = error, playerCount = playerCount, uptime = uptime }; } private DiscordWebhookPayload BuildEmbedPayload(WebhookEventType eventType, string serverName, string worldName, string backupFolder, string pathValue, string error, int playerCount, string uptime) { List<DiscordEmbedField> list = new List<DiscordEmbedField> { new DiscordEmbedField { name = "Szerver", value = GetDiscordSafeValue(serverName), inline = true }, new DiscordEmbedField { name = "Világ", value = GetDiscordSafeValue(worldName), inline = true }, new DiscordEmbedField { name = "Játékosok", value = playerCount.ToString(), inline = true }, new DiscordEmbedField { name = "Uptime", value = GetDiscordSafeValue(uptime), inline = true }, new DiscordEmbedField { name = "Idő", value = GetDiscordSafeValue(GetTime().ToString("yyyy-MM-dd HH:mm:ss")), inline = true } }; string title; string description; int color; switch (eventType) { case WebhookEventType.BackupSuccess: title = "✅ Backup elkészült"; description = "Az automatikus mentés sikeresen lefutott."; color = 5763719; list.Add(new DiscordEmbedField { name = "Megtartott mentések", value = config.backup.keepLast.ToString(), inline = true }); list.Add(new DiscordEmbedField { name = "Mappa", value = GetDiscordSafeValue(backupFolder), inline = false }); list.Add(new DiscordEmbedField { name = "Fájl", value = GetDiscordSafeValue(string.IsNullOrWhiteSpace(pathValue) ? "-" : Path.GetFileName(pathValue)), inline = true }); list.Add(new DiscordEmbedField { name = "Teljes útvonal", value = GetDiscordSafeValue(string.IsNullOrWhiteSpace(pathValue) ? "-" : pathValue), inline = false }); break; case WebhookEventType.BackupError: title = "❌ Backup hiba"; description = "Hiba történt az automatikus mentés közben."; color = 15548997; list.Add(new DiscordEmbedField { name = "Hiba", value = GetDiscordSafeValue(error), inline = false }); break; case WebhookEventType.Restart: title = "\ud83d\udd01 Szerver restart indul"; description = "Az időzített restart folyamat elindult."; color = 15105570; break; case WebhookEventType.RestartError: title = "❌ Restart hiba"; description = "Hiba történt a restart folyamat közben."; color = 15548997; list.Add(new DiscordEmbedField { name = "Hiba", value = GetDiscordSafeValue(error), inline = false }); break; default: title = "Hardheim Timed Save"; description = "Webhook esemény"; color = 3447003; break; } DiscordEmbed discordEmbed = new DiscordEmbed { title = title, description = description, color = color, fields = list.ToArray(), timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"), footer = new DiscordEmbedFooter { text = "Hardheim Timed Save" } }; DiscordWebhookPayload discordWebhookPayload = new DiscordWebhookPayload(); discordWebhookPayload.content = BuildWebhookMessage(GetTemplateForEvent(eventType), serverName, worldName, backupFolder, pathValue, error, playerCount, uptime); discordWebhookPayload.username = (string.IsNullOrWhiteSpace(config.webhook.username) ? "Hardheim Timed Save" : config.webhook.username); discordWebhookPayload.avatar_url = (string.IsNullOrWhiteSpace(config.webhook.avatarUrl) ? null : config.webhook.avatarUrl); discordWebhookPayload.embeds = new DiscordEmbed[1] { discordEmbed }; return discordWebhookPayload; } private string GetDiscordSafeValue(string value) { if (string.IsNullOrWhiteSpace(value)) { return "-"; } string text = value.Replace("\r", " ").Replace("\n", " ").Trim(); if (string.IsNullOrWhiteSpace(text)) { return "-"; } if (text.Length > 1000) { text = text.Substring(0, 1000) + "..."; } return text; } private int GetOnlinePlayerCount() { try { return Player.GetAllPlayers().Count; } catch { return 0; } } private string GetFormattedUptime() { TimeSpan timeSpan = DateTime.UtcNow - pluginStartUtc; return string.Format("{0:%d} nap {0:hh\\:mm\\:ss}", timeSpan); } private void SendCenterMessage(string msg) { if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "ShowMessage", new object[2] { 2, msg }); } } private void LogInfo(string message) { if (config == null || config.logToConsole) { Log.LogInfo((object)message); } } private void LogWarning(string message) { Log.LogWarning((object)message); } private void LogError(string message) { Log.LogError((object)message); } } namespace HardheimTimedSave; public class Class1 { }
YamlDotNet.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using System.Threading; using Microsoft.CodeAnalysis; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.ObjectPool; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Callbacks; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: ComVisible(false)] [assembly: AssemblyFileVersion("16.3.0.0")] [assembly: AssemblyInformationalVersion("16.3.0")] [assembly: AssemblyTitle("YamlDotNet")] [assembly: AssemblyDescription("The YamlDotNet library.")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("YamlDotNet")] [assembly: AssemblyCopyright("Copyright (c) Antoine Aubry and contributors 2008 - 2019")] [assembly: AssemblyTrademark("")] [assembly: CLSCompliant(true)] [assembly: InternalsVisibleTo("YamlDotNet.Test, PublicKey=002400000480000094000000060200000024000052534131000400000100010065e52a453dde5c5b4be5bbe2205755727fce80244b79b894faf8793d80f7db9a96d360b51c220782db32aacee4cb5b8a91bee33aeec700e1f21895c4baadef501eeeac609220d1651603b378173811ee5bb6a002df973d38821bd2fef820c00c174a69faec326a1983b570f07ec66147026b9c8753465de3a8d0c44b613b02af")] [assembly: TargetFramework(".NETFramework,Version=v4.7", FrameworkDisplayName = ".NET Framework 4.7")] [assembly: AssemblyVersion("16.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace YamlDotNet { internal sealed class CultureInfoAdapter : CultureInfo { private readonly IFormatProvider provider; public CultureInfoAdapter(CultureInfo baseCulture, IFormatProvider provider) : base(baseCulture.Name) { this.provider = provider; } public override object? GetFormat(Type formatType) { return provider.GetFormat(formatType); } } internal static class Polyfills { [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool Contains(this string source, char c) { return source.IndexOf(c) != -1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool EndsWith(this string source, char c) { if (source.Length > 0) { return source[source.Length - 1] == c; } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool StartsWith(this string source, char c) { if (source.Length > 0) { return source[0] == c; } return false; } } internal static class PropertyInfoExtensions { public static object? ReadValue(this PropertyInfo property, object target) { return property.GetValue(target, null); } } internal static class ReflectionExtensions { private static readonly Func<PropertyInfo, bool> IsInstance = (PropertyInfo property) => !(property.GetMethod ?? property.SetMethod).IsStatic; private static readonly Func<PropertyInfo, bool> IsInstancePublic = (PropertyInfo property) => IsInstance(property) && (property.GetMethod ?? property.SetMethod).IsPublic; public static Type? BaseType(this Type type) { return type.GetTypeInfo().BaseType; } public static bool IsValueType(this Type type) { return type.GetTypeInfo().IsValueType; } public static bool IsGenericType(this Type type) { return type.GetTypeInfo().IsGenericType; } public static bool IsGenericTypeDefinition(this Type type) { return type.GetTypeInfo().IsGenericTypeDefinition; } public static Type? GetImplementationOfOpenGenericInterface(this Type type, Type openGenericType) { if (!openGenericType.IsGenericType || !openGenericType.IsInterface) { throw new ArgumentException("The type must be a generic type definition and an interface", "openGenericType"); } if (IsGenericDefinitionOfType(type, openGenericType)) { return type; } return type.FindInterfaces((Type t, object context) => IsGenericDefinitionOfType(t, context), openGenericType).FirstOrDefault(); static bool IsGenericDefinitionOfType(Type t, object? context) { if (t.IsGenericType) { return t.GetGenericTypeDefinition() == (Type)context; } return false; } } public static bool IsInterface(this Type type) { return type.GetTypeInfo().IsInterface; } public static bool IsEnum(this Type type) { return type.GetTypeInfo().IsEnum; } public static bool IsRequired(this MemberInfo member) { return member.GetCustomAttributes(inherit: true).Any((object x) => x.GetType().FullName == "System.Runtime.CompilerServices.RequiredMemberAttribute"); } public static bool HasDefaultConstructor(this Type type, bool allowPrivateConstructors) { BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public; if (allowPrivateConstructors) { bindingFlags |= BindingFlags.NonPublic; } if (!type.IsValueType) { return type.GetConstructor(bindingFlags, null, Type.EmptyTypes, null) != null; } return true; } public static bool IsAssignableFrom(this Type type, Type source) { return type.IsAssignableFrom(source.GetTypeInfo()); } public static bool IsAssignableFrom(this Type type, TypeInfo source) { return type.GetTypeInfo().IsAssignableFrom(source); } public static TypeCode GetTypeCode(this Type type) { if (type.IsEnum()) { type = Enum.GetUnderlyingType(type); } if (type == typeof(bool)) { return TypeCode.Boolean; } if (type == typeof(char)) { return TypeCode.Char; } if (type == typeof(sbyte)) { return TypeCode.SByte; } if (type == typeof(byte)) { return TypeCode.Byte; } if (type == typeof(short)) { return TypeCode.Int16; } if (type == typeof(ushort)) { return TypeCode.UInt16; } if (type == typeof(int)) { return TypeCode.Int32; } if (type == typeof(uint)) { return TypeCode.UInt32; } if (type == typeof(long)) { return TypeCode.Int64; } if (type == typeof(ulong)) { return TypeCode.UInt64; } if (type == typeof(float)) { return TypeCode.Single; } if (type == typeof(double)) { return TypeCode.Double; } if (type == typeof(decimal)) { return TypeCode.Decimal; } if (type == typeof(DateTime)) { return TypeCode.DateTime; } if (type == typeof(string)) { return TypeCode.String; } return TypeCode.Object; } public static bool IsDbNull(this object value) { return value?.GetType()?.FullName == "System.DBNull"; } public static Type[] GetGenericArguments(this Type type) { return type.GetTypeInfo().GenericTypeArguments; } public static PropertyInfo? GetPublicProperty(this Type type, string name) { string name2 = name; return type.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public).FirstOrDefault((PropertyInfo p) => p.Name == name2); } public static FieldInfo? GetPublicStaticField(this Type type, string name) { return type.GetRuntimeField(name); } public static IEnumerable<PropertyInfo> GetProperties(this Type type, bool includeNonPublic) { Func<PropertyInfo, bool> predicate = (includeNonPublic ? IsInstance : IsInstancePublic); if (!type.IsInterface()) { return type.GetRuntimeProperties().Where(predicate); } return new Type[1] { type }.Concat(type.GetInterfaces()).SelectMany((Type i) => i.GetRuntimeProperties().Where(predicate)); } public static IEnumerable<PropertyInfo> GetPublicProperties(this Type type) { return type.GetProperties(includeNonPublic: false); } public static IEnumerable<FieldInfo> GetPublicFields(this Type type) { return from f in type.GetRuntimeFields() where !f.IsStatic && f.IsPublic select f; } public static IEnumerable<MethodInfo> GetPublicStaticMethods(this Type type) { return from m in type.GetRuntimeMethods() where m.IsPublic && m.IsStatic select m; } public static MethodInfo GetPrivateStaticMethod(this Type type, string name) { string name2 = name; return type.GetRuntimeMethods().FirstOrDefault((MethodInfo m) => !m.IsPublic && m.IsStatic && m.Name.Equals(name2)) ?? throw new MissingMethodException("Expected to find a method named '" + name2 + "' in '" + type.FullName + "'."); } public static MethodInfo? GetPublicStaticMethod(this Type type, string name, params Type[] parameterTypes) { string name2 = name; Type[] parameterTypes2 = parameterTypes; return type.GetRuntimeMethods().FirstOrDefault(delegate(MethodInfo m) { if (m.IsPublic && m.IsStatic && m.Name.Equals(name2)) { ParameterInfo[] parameters = m.GetParameters(); if (parameters.Length == parameterTypes2.Length) { return parameters.Zip(parameterTypes2, (ParameterInfo pi, Type pt) => pi.ParameterType == pt).All((bool r) => r); } return false; } return false; }); } public static MethodInfo? GetPublicInstanceMethod(this Type type, string name) { string name2 = name; return type.GetRuntimeMethods().FirstOrDefault((MethodInfo m) => m.IsPublic && !m.IsStatic && m.Name.Equals(name2)); } public static MethodInfo? GetGetMethod(this PropertyInfo property, bool nonPublic) { MethodInfo methodInfo = property.GetMethod; if (!nonPublic && !methodInfo.IsPublic) { methodInfo = null; } return methodInfo; } public static MethodInfo? GetSetMethod(this PropertyInfo property) { return property.SetMethod; } public static IEnumerable<Type> GetInterfaces(this Type type) { return type.GetTypeInfo().ImplementedInterfaces; } public static bool IsInstanceOf(this Type type, object o) { if (!(o.GetType() == type)) { return o.GetType().GetTypeInfo().IsSubclassOf(type); } return true; } public static Attribute[] GetAllCustomAttributes<TAttribute>(this PropertyInfo member) { return Attribute.GetCustomAttributes(member, typeof(TAttribute), inherit: true); } public static bool AcceptsNull(this MemberInfo member) { object[] customAttributes = member.DeclaringType.GetCustomAttributes(inherit: true); object obj = customAttributes.FirstOrDefault((object x) => x.GetType().FullName == "System.Runtime.CompilerServices.NullableContextAttribute"); int num = 0; if (obj != null) { Type type = obj.GetType(); PropertyInfo property = type.GetProperty("Flag"); num = (byte)property.GetValue(obj); } object[] customAttributes2 = member.GetCustomAttributes(inherit: true); object obj2 = customAttributes2.FirstOrDefault((object x) => x.GetType().FullName == "System.Runtime.CompilerServices.NullableAttribute"); PropertyInfo propertyInfo = (obj2?.GetType())?.GetProperty("NullableFlags"); byte[] source = (byte[])propertyInfo.GetValue(obj2); return source.Any((byte x) => x == 2) || num == 2; } } internal static class StandardRegexOptions { public const RegexOptions Compiled = RegexOptions.Compiled; } } namespace YamlDotNet.Serialization { public abstract class BuilderSkeleton<TBuilder> where TBuilder : BuilderSkeleton<TBuilder> { internal INamingConvention namingConvention = NullNamingConvention.Instance; internal INamingConvention enumNamingConvention = NullNamingConvention.Instance; internal ITypeResolver typeResolver; internal readonly YamlAttributeOverrides overrides; internal readonly LazyComponentRegistrationList<Nothing, IYamlTypeConverter> typeConverterFactories; internal readonly LazyComponentRegistrationList<ITypeInspector, ITypeInspector> typeInspectorFactories; internal bool ignoreFields; internal bool includeNonPublicProperties; internal Settings settings; internal YamlFormatter yamlFormatter = YamlFormatter.Default; protected abstract TBuilder Self { get; } internal BuilderSkeleton(ITypeResolver typeResolver) { overrides = new YamlAttributeOverrides(); typeConverterFactories = new LazyComponentRegistrationList<Nothing, IYamlTypeConverter> { { typeof(YamlDotNet.Serialization.Converters.GuidConverter), (Nothing _) => new YamlDotNet.Serialization.Converters.GuidConverter(jsonCompatible: false) }, { typeof(SystemTypeConverter), (Nothing _) => new SystemTypeConverter() } }; typeInspectorFactories = new LazyComponentRegistrationList<ITypeInspector, ITypeInspector>(); this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver"); settings = new Settings(); } public TBuilder IgnoreFields() { ignoreFields = true; return Self; } public TBuilder IncludeNonPublicProperties() { includeNonPublicProperties = true; return Self; } public TBuilder EnablePrivateConstructors() { settings.AllowPrivateConstructors = true; return Self; } public TBuilder WithNamingConvention(INamingConvention namingConvention) { this.namingConvention = namingConvention ?? throw new ArgumentNullException("namingConvention"); return Self; } public TBuilder WithEnumNamingConvention(INamingConvention enumNamingConvention) { this.enumNamingConvention = enumNamingConvention; return Self; } public TBuilder WithTypeResolver(ITypeResolver typeResolver) { this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver"); return Self; } public abstract TBuilder WithTagMapping(TagName tag, Type type); public TBuilder WithAttributeOverride<TClass>(Expression<Func<TClass, object>> propertyAccessor, Attribute attribute) { overrides.Add(propertyAccessor, attribute); return Self; } public TBuilder WithAttributeOverride(Type type, string member, Attribute attribute) { overrides.Add(type, member, attribute); return Self; } public TBuilder WithTypeConverter(IYamlTypeConverter typeConverter) { return WithTypeConverter(typeConverter, delegate(IRegistrationLocationSelectionSyntax<IYamlTypeConverter> w) { w.OnTop(); }); } public TBuilder WithTypeConverter(IYamlTypeConverter typeConverter, Action<IRegistrationLocationSelectionSyntax<IYamlTypeConverter>> where) { IYamlTypeConverter typeConverter2 = typeConverter; if (typeConverter2 == null) { throw new ArgumentNullException("typeConverter"); } if (where == null) { throw new ArgumentNullException("where"); } where(typeConverterFactories.CreateRegistrationLocationSelector(typeConverter2.GetType(), (Nothing _) => typeConverter2)); return Self; } public TBuilder WithTypeConverter<TYamlTypeConverter>(WrapperFactory<IYamlTypeConverter, IYamlTypeConverter> typeConverterFactory, Action<ITrackingRegistrationLocationSelectionSyntax<IYamlTypeConverter>> where) where TYamlTypeConverter : IYamlTypeConverter { WrapperFactory<IYamlTypeConverter, IYamlTypeConverter> typeConverterFactory2 = typeConverterFactory; if (typeConverterFactory2 == null) { throw new ArgumentNullException("typeConverterFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(typeConverterFactories.CreateTrackingRegistrationLocationSelector(typeof(TYamlTypeConverter), (IYamlTypeConverter wrapped, Nothing _) => typeConverterFactory2(wrapped))); return Self; } public TBuilder WithoutTypeConverter<TYamlTypeConverter>() where TYamlTypeConverter : IYamlTypeConverter { return WithoutTypeConverter(typeof(TYamlTypeConverter)); } public TBuilder WithoutTypeConverter(Type converterType) { if (converterType == null) { throw new ArgumentNullException("converterType"); } typeConverterFactories.Remove(converterType); return Self; } public TBuilder WithTypeInspector<TTypeInspector>(Func<ITypeInspector, TTypeInspector> typeInspectorFactory) where TTypeInspector : ITypeInspector { return WithTypeInspector(typeInspectorFactory, delegate(IRegistrationLocationSelectionSyntax<ITypeInspector> w) { w.OnTop(); }); } public TBuilder WithTypeInspector<TTypeInspector>(Func<ITypeInspector, TTypeInspector> typeInspectorFactory, Action<IRegistrationLocationSelectionSyntax<ITypeInspector>> where) where TTypeInspector : ITypeInspector { Func<ITypeInspector, TTypeInspector> typeInspectorFactory2 = typeInspectorFactory; if (typeInspectorFactory2 == null) { throw new ArgumentNullException("typeInspectorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(typeInspectorFactories.CreateRegistrationLocationSelector(typeof(TTypeInspector), (ITypeInspector inner) => typeInspectorFactory2(inner))); return Self; } public TBuilder WithTypeInspector<TTypeInspector>(WrapperFactory<ITypeInspector, ITypeInspector, TTypeInspector> typeInspectorFactory, Action<ITrackingRegistrationLocationSelectionSyntax<ITypeInspector>> where) where TTypeInspector : ITypeInspector { WrapperFactory<ITypeInspector, ITypeInspector, TTypeInspector> typeInspectorFactory2 = typeInspectorFactory; if (typeInspectorFactory2 == null) { throw new ArgumentNullException("typeInspectorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(typeInspectorFactories.CreateTrackingRegistrationLocationSelector(typeof(TTypeInspector), (ITypeInspector wrapped, ITypeInspector inner) => typeInspectorFactory2(wrapped, inner))); return Self; } public TBuilder WithoutTypeInspector<TTypeInspector>() where TTypeInspector : ITypeInspector { return WithoutTypeInspector(typeof(TTypeInspector)); } public TBuilder WithoutTypeInspector(Type inspectorType) { if (inspectorType == null) { throw new ArgumentNullException("inspectorType"); } typeInspectorFactories.Remove(inspectorType); return Self; } public TBuilder WithYamlFormatter(YamlFormatter formatter) { yamlFormatter = formatter ?? throw new ArgumentNullException("formatter"); return Self; } protected IEnumerable<IYamlTypeConverter> BuildTypeConverters() { return typeConverterFactories.BuildComponentList(); } } public delegate TComponent WrapperFactory<TComponentBase, TComponent>(TComponentBase wrapped) where TComponent : TComponentBase; public delegate TComponent WrapperFactory<TArgument, TComponentBase, TComponent>(TComponentBase wrapped, TArgument argument) where TComponent : TComponentBase; [Flags] public enum DefaultValuesHandling { Preserve = 0, OmitNull = 1, OmitDefaults = 2, OmitEmptyCollections = 4 } public sealed class Deserializer : IDeserializer { private readonly IValueDeserializer valueDeserializer; public Deserializer() : this(new DeserializerBuilder().BuildValueDeserializer()) { } private Deserializer(IValueDeserializer valueDeserializer) { this.valueDeserializer = valueDeserializer ?? throw new ArgumentNullException("valueDeserializer"); } public static Deserializer FromValueDeserializer(IValueDeserializer valueDeserializer) { return new Deserializer(valueDeserializer); } public T Deserialize<T>(string input) { using StringReader input2 = new StringReader(input); return Deserialize<T>(input2); } public T Deserialize<T>(TextReader input) { return Deserialize<T>(new Parser(input)); } public T Deserialize<T>(IParser parser) { return (T)Deserialize(parser, typeof(T)); } public object? Deserialize(string input) { return Deserialize<object>(input); } public object? Deserialize(TextReader input) { return Deserialize<object>(input); } public object? Deserialize(IParser parser) { return Deserialize<object>(parser); } public object? Deserialize(string input, Type type) { using StringReader input2 = new StringReader(input); return Deserialize(input2, type); } public object? Deserialize(TextReader input, Type type) { return Deserialize(new Parser(input), type); } public object? Deserialize(IParser parser, Type type) { if (parser == null) { throw new ArgumentNullException("parser"); } if (type == null) { throw new ArgumentNullException("type"); } YamlDotNet.Core.Events.StreamStart @event; bool flag = parser.TryConsume<YamlDotNet.Core.Events.StreamStart>(out @event); YamlDotNet.Core.Events.DocumentStart event2; bool flag2 = parser.TryConsume<YamlDotNet.Core.Events.DocumentStart>(out event2); object result = null; if (!parser.Accept<YamlDotNet.Core.Events.DocumentEnd>(out var _) && !parser.Accept<YamlDotNet.Core.Events.StreamEnd>(out var _)) { using SerializerState serializerState = new SerializerState(); result = valueDeserializer.DeserializeValue(parser, type, serializerState, valueDeserializer); serializerState.OnDeserialization(); } if (flag2) { parser.Consume<YamlDotNet.Core.Events.DocumentEnd>(); } if (flag) { parser.Consume<YamlDotNet.Core.Events.StreamEnd>(); } return result; } } public sealed class DeserializerBuilder : BuilderSkeleton<DeserializerBuilder> { private Lazy<IObjectFactory> objectFactory; private readonly LazyComponentRegistrationList<Nothing, INodeDeserializer> nodeDeserializerFactories; private readonly LazyComponentRegistrationList<Nothing, INodeTypeResolver> nodeTypeResolverFactories; private readonly Dictionary<TagName, Type> tagMappings; private readonly Dictionary<Type, Type> typeMappings; private readonly ITypeConverter typeConverter; private bool ignoreUnmatched; private bool duplicateKeyChecking; private bool attemptUnknownTypeDeserialization; private bool enforceNullability; private bool caseInsensitivePropertyMatching; private bool enforceRequiredProperties; protected override DeserializerBuilder Self => this; public DeserializerBuilder() : base((ITypeResolver)new StaticTypeResolver()) { typeMappings = new Dictionary<Type, Type>(); objectFactory = new Lazy<IObjectFactory>(() => new DefaultObjectFactory(typeMappings, settings), isThreadSafe: true); tagMappings = new Dictionary<TagName, Type> { { FailsafeSchema.Tags.Map, typeof(Dictionary<object, object>) }, { FailsafeSchema.Tags.Str, typeof(string) }, { JsonSchema.Tags.Bool, typeof(bool) }, { JsonSchema.Tags.Float, typeof(double) }, { JsonSchema.Tags.Int, typeof(int) }, { DefaultSchema.Tags.Timestamp, typeof(DateTime) } }; typeInspectorFactories.Add(typeof(CachedTypeInspector), (ITypeInspector inner) => new CachedTypeInspector(inner)); typeInspectorFactories.Add(typeof(NamingConventionTypeInspector), (ITypeInspector inner) => (!(namingConvention is NullNamingConvention)) ? new NamingConventionTypeInspector(inner, namingConvention) : inner); typeInspectorFactories.Add(typeof(YamlAttributesTypeInspector), (ITypeInspector inner) => new YamlAttributesTypeInspector(inner)); typeInspectorFactories.Add(typeof(YamlAttributeOverridesInspector), (ITypeInspector inner) => (overrides == null) ? inner : new YamlAttributeOverridesInspector(inner, overrides.Clone())); typeInspectorFactories.Add(typeof(ReadableAndWritablePropertiesTypeInspector), (ITypeInspector inner) => new ReadableAndWritablePropertiesTypeInspector(inner)); nodeDeserializerFactories = new LazyComponentRegistrationList<Nothing, INodeDeserializer> { { typeof(YamlConvertibleNodeDeserializer), (Nothing _) => new YamlConvertibleNodeDeserializer(objectFactory.Value) }, { typeof(YamlSerializableNodeDeserializer), (Nothing _) => new YamlSerializableNodeDeserializer(objectFactory.Value) }, { typeof(TypeConverterNodeDeserializer), (Nothing _) => new TypeConverterNodeDeserializer(BuildTypeConverters()) }, { typeof(NullNodeDeserializer), (Nothing _) => new NullNodeDeserializer() }, { typeof(ScalarNodeDeserializer), (Nothing _) => new ScalarNodeDeserializer(attemptUnknownTypeDeserialization, typeConverter, BuildTypeInspector(), yamlFormatter, enumNamingConvention) }, { typeof(ArrayNodeDeserializer), (Nothing _) => new ArrayNodeDeserializer(enumNamingConvention, BuildTypeInspector()) }, { typeof(DictionaryNodeDeserializer), (Nothing _) => new DictionaryNodeDeserializer(objectFactory.Value, duplicateKeyChecking) }, { typeof(CollectionNodeDeserializer), (Nothing _) => new CollectionNodeDeserializer(objectFactory.Value, enumNamingConvention, BuildTypeInspector()) }, { typeof(EnumerableNodeDeserializer), (Nothing _) => new EnumerableNodeDeserializer() }, { typeof(ObjectNodeDeserializer), (Nothing _) => new ObjectNodeDeserializer(objectFactory.Value, BuildTypeInspector(), ignoreUnmatched, duplicateKeyChecking, typeConverter, enumNamingConvention, enforceNullability, caseInsensitivePropertyMatching, enforceRequiredProperties, BuildTypeConverters()) }, { typeof(FsharpListNodeDeserializer), (Nothing _) => new FsharpListNodeDeserializer(BuildTypeInspector(), enumNamingConvention) } }; nodeTypeResolverFactories = new LazyComponentRegistrationList<Nothing, INodeTypeResolver> { { typeof(MappingNodeTypeResolver), (Nothing _) => new MappingNodeTypeResolver(typeMappings) }, { typeof(YamlConvertibleTypeResolver), (Nothing _) => new YamlConvertibleTypeResolver() }, { typeof(YamlSerializableTypeResolver), (Nothing _) => new YamlSerializableTypeResolver() }, { typeof(TagNodeTypeResolver), (Nothing _) => new TagNodeTypeResolver(tagMappings) }, { typeof(PreventUnknownTagsNodeTypeResolver), (Nothing _) => new PreventUnknownTagsNodeTypeResolver() }, { typeof(DefaultContainersNodeTypeResolver), (Nothing _) => new DefaultContainersNodeTypeResolver() } }; typeConverter = new ReflectionTypeConverter(); } public ITypeInspector BuildTypeInspector() { ITypeInspector typeInspector = new WritablePropertiesTypeInspector(typeResolver, includeNonPublicProperties); if (!ignoreFields) { typeInspector = new CompositeTypeInspector(new ReadableFieldsTypeInspector(typeResolver), typeInspector); } return typeInspectorFactories.BuildComponentChain(typeInspector); } public DeserializerBuilder WithAttemptingUnquotedStringTypeDeserialization() { attemptUnknownTypeDeserialization = true; return this; } public DeserializerBuilder WithObjectFactory(IObjectFactory objectFactory) { IObjectFactory objectFactory2 = objectFactory; if (objectFactory2 == null) { throw new ArgumentNullException("objectFactory"); } this.objectFactory = new Lazy<IObjectFactory>(() => objectFactory2, isThreadSafe: true); return this; } public DeserializerBuilder WithObjectFactory(Func<Type, object> objectFactory) { if (objectFactory == null) { throw new ArgumentNullException("objectFactory"); } return WithObjectFactory(new LambdaObjectFactory(objectFactory)); } public DeserializerBuilder WithNodeDeserializer(INodeDeserializer nodeDeserializer) { return WithNodeDeserializer(nodeDeserializer, delegate(IRegistrationLocationSelectionSyntax<INodeDeserializer> w) { w.OnTop(); }); } public DeserializerBuilder WithNodeDeserializer(INodeDeserializer nodeDeserializer, Action<IRegistrationLocationSelectionSyntax<INodeDeserializer>> where) { INodeDeserializer nodeDeserializer2 = nodeDeserializer; if (nodeDeserializer2 == null) { throw new ArgumentNullException("nodeDeserializer"); } if (where == null) { throw new ArgumentNullException("where"); } where(nodeDeserializerFactories.CreateRegistrationLocationSelector(nodeDeserializer2.GetType(), (Nothing _) => nodeDeserializer2)); return this; } public DeserializerBuilder WithNodeDeserializer<TNodeDeserializer>(WrapperFactory<INodeDeserializer, TNodeDeserializer> nodeDeserializerFactory, Action<ITrackingRegistrationLocationSelectionSyntax<INodeDeserializer>> where) where TNodeDeserializer : INodeDeserializer { WrapperFactory<INodeDeserializer, TNodeDeserializer> nodeDeserializerFactory2 = nodeDeserializerFactory; if (nodeDeserializerFactory2 == null) { throw new ArgumentNullException("nodeDeserializerFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(nodeDeserializerFactories.CreateTrackingRegistrationLocationSelector(typeof(TNodeDeserializer), (INodeDeserializer wrapped, Nothing _) => nodeDeserializerFactory2(wrapped))); return this; } public DeserializerBuilder WithoutNodeDeserializer<TNodeDeserializer>() where TNodeDeserializer : INodeDeserializer { return WithoutNodeDeserializer(typeof(TNodeDeserializer)); } public DeserializerBuilder WithoutNodeDeserializer(Type nodeDeserializerType) { if (nodeDeserializerType == null) { throw new ArgumentNullException("nodeDeserializerType"); } nodeDeserializerFactories.Remove(nodeDeserializerType); return this; } public DeserializerBuilder WithTypeDiscriminatingNodeDeserializer(Action<ITypeDiscriminatingNodeDeserializerOptions> configureTypeDiscriminatingNodeDeserializerOptions, int maxDepth = -1, int maxLength = -1) { TypeDiscriminatingNodeDeserializerOptions typeDiscriminatingNodeDeserializerOptions = new TypeDiscriminatingNodeDeserializerOptions(); configureTypeDiscriminatingNodeDeserializerOptions(typeDiscriminatingNodeDeserializerOptions); TypeDiscriminatingNodeDeserializer nodeDeserializer = new TypeDiscriminatingNodeDeserializer(nodeDeserializerFactories.BuildComponentList(), typeDiscriminatingNodeDeserializerOptions.discriminators, maxDepth, maxLength); return WithNodeDeserializer(nodeDeserializer, delegate(IRegistrationLocationSelectionSyntax<INodeDeserializer> s) { s.Before<DictionaryNodeDeserializer>(); }); } public DeserializerBuilder WithNodeTypeResolver(INodeTypeResolver nodeTypeResolver) { return WithNodeTypeResolver(nodeTypeResolver, delegate(IRegistrationLocationSelectionSyntax<INodeTypeResolver> w) { w.OnTop(); }); } public DeserializerBuilder WithNodeTypeResolver(INodeTypeResolver nodeTypeResolver, Action<IRegistrationLocationSelectionSyntax<INodeTypeResolver>> where) { INodeTypeResolver nodeTypeResolver2 = nodeTypeResolver; if (nodeTypeResolver2 == null) { throw new ArgumentNullException("nodeTypeResolver"); } if (where == null) { throw new ArgumentNullException("where"); } where(nodeTypeResolverFactories.CreateRegistrationLocationSelector(nodeTypeResolver2.GetType(), (Nothing _) => nodeTypeResolver2)); return this; } public DeserializerBuilder WithNodeTypeResolver<TNodeTypeResolver>(WrapperFactory<INodeTypeResolver, TNodeTypeResolver> nodeTypeResolverFactory, Action<ITrackingRegistrationLocationSelectionSyntax<INodeTypeResolver>> where) where TNodeTypeResolver : INodeTypeResolver { WrapperFactory<INodeTypeResolver, TNodeTypeResolver> nodeTypeResolverFactory2 = nodeTypeResolverFactory; if (nodeTypeResolverFactory2 == null) { throw new ArgumentNullException("nodeTypeResolverFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(nodeTypeResolverFactories.CreateTrackingRegistrationLocationSelector(typeof(TNodeTypeResolver), (INodeTypeResolver wrapped, Nothing _) => nodeTypeResolverFactory2(wrapped))); return this; } public DeserializerBuilder WithCaseInsensitivePropertyMatching() { caseInsensitivePropertyMatching = true; return this; } public DeserializerBuilder WithEnforceNullability() { enforceNullability = true; return this; } public DeserializerBuilder WithEnforceRequiredMembers() { enforceRequiredProperties = true; return this; } public DeserializerBuilder WithoutNodeTypeResolver<TNodeTypeResolver>() where TNodeTypeResolver : INodeTypeResolver { return WithoutNodeTypeResolver(typeof(TNodeTypeResolver)); } public DeserializerBuilder WithoutNodeTypeResolver(Type nodeTypeResolverType) { if (nodeTypeResolverType == null) { throw new ArgumentNullException("nodeTypeResolverType"); } nodeTypeResolverFactories.Remove(nodeTypeResolverType); return this; } public override DeserializerBuilder WithTagMapping(TagName tag, Type type) { if (tag.IsEmpty) { throw new ArgumentException("Non-specific tags cannot be maped"); } if (type == null) { throw new ArgumentNullException("type"); } if (tagMappings.TryGetValue(tag, out Type value)) { throw new ArgumentException($"Type already has a registered type '{value.FullName}' for tag '{tag}'", "tag"); } tagMappings.Add(tag, type); return this; } public DeserializerBuilder WithTypeMapping<TInterface, TConcrete>() where TConcrete : TInterface { Type typeFromHandle = typeof(TInterface); Type typeFromHandle2 = typeof(TConcrete); if (!typeFromHandle.IsAssignableFrom(typeFromHandle2)) { throw new InvalidOperationException("The type '" + typeFromHandle2.Name + "' does not implement interface '" + typeFromHandle.Name + "'."); } if (!DictionaryExtensions.TryAdd(typeMappings, typeFromHandle, typeFromHandle2)) { typeMappings[typeFromHandle] = typeFromHandle2; } return this; } public DeserializerBuilder WithoutTagMapping(TagName tag) { if (tag.IsEmpty) { throw new ArgumentException("Non-specific tags cannot be maped"); } if (!tagMappings.Remove(tag)) { throw new KeyNotFoundException($"Tag '{tag}' is not registered"); } return this; } public DeserializerBuilder IgnoreUnmatchedProperties() { ignoreUnmatched = true; return this; } public DeserializerBuilder WithDuplicateKeyChecking() { duplicateKeyChecking = true; return this; } public IDeserializer Build() { if (FsharpHelper.Instance == null) { FsharpHelper.Instance = new DefaultFsharpHelper(); } return Deserializer.FromValueDeserializer(BuildValueDeserializer()); } public IValueDeserializer BuildValueDeserializer() { return new AliasValueDeserializer(new NodeValueDeserializer(nodeDeserializerFactories.BuildComponentList(), nodeTypeResolverFactories.BuildComponentList(), typeConverter, enumNamingConvention, BuildTypeInspector())); } } public sealed class EmissionPhaseObjectGraphVisitorArgs { private readonly IEnumerable<IObjectGraphVisitor<Nothing>> preProcessingPhaseVisitors; public IObjectGraphVisitor<IEmitter> InnerVisitor { get; private set; } public IEventEmitter EventEmitter { get; private set; } public ObjectSerializer NestedObjectSerializer { get; private set; } public IEnumerable<IYamlTypeConverter> TypeConverters { get; private set; } public EmissionPhaseObjectGraphVisitorArgs(IObjectGraphVisitor<IEmitter> innerVisitor, IEventEmitter eventEmitter, IEnumerable<IObjectGraphVisitor<Nothing>> preProcessingPhaseVisitors, IEnumerable<IYamlTypeConverter> typeConverters, ObjectSerializer nestedObjectSerializer) { InnerVisitor = innerVisitor ?? throw new ArgumentNullException("innerVisitor"); EventEmitter = eventEmitter ?? throw new ArgumentNullException("eventEmitter"); this.preProcessingPhaseVisitors = preProcessingPhaseVisitors ?? throw new ArgumentNullException("preProcessingPhaseVisitors"); TypeConverters = typeConverters ?? throw new ArgumentNullException("typeConverters"); NestedObjectSerializer = nestedObjectSerializer ?? throw new ArgumentNullException("nestedObjectSerializer"); } public T GetPreProcessingPhaseObjectGraphVisitor<T>() where T : IObjectGraphVisitor<Nothing> { return preProcessingPhaseVisitors.OfType<T>().Single(); } } public abstract class EventInfo { public IObjectDescriptor Source { get; } protected EventInfo(IObjectDescriptor source) { Source = source ?? throw new ArgumentNullException("source"); } } public class AliasEventInfo : EventInfo { public AnchorName Alias { get; } public bool NeedsExpansion { get; set; } public AliasEventInfo(IObjectDescriptor source, AnchorName alias) : base(source) { if (alias.IsEmpty) { throw new ArgumentNullException("alias"); } Alias = alias; } } public class ObjectEventInfo : EventInfo { public AnchorName Anchor { get; set; } public TagName Tag { get; set; } protected ObjectEventInfo(IObjectDescriptor source) : base(source) { } } public sealed class ScalarEventInfo : ObjectEventInfo { public string RenderedValue { get; set; } public ScalarStyle Style { get; set; } public bool IsPlainImplicit { get; set; } public bool IsQuotedImplicit { get; set; } public ScalarEventInfo(IObjectDescriptor source) : base(source) { Style = source.ScalarStyle; RenderedValue = string.Empty; } } public sealed class MappingStartEventInfo : ObjectEventInfo { public bool IsImplicit { get; set; } public MappingStyle Style { get; set; } public MappingStartEventInfo(IObjectDescriptor source) : base(source) { } } public sealed class MappingEndEventInfo : EventInfo { public MappingEndEventInfo(IObjectDescriptor source) : base(source) { } } public sealed class SequenceStartEventInfo : ObjectEventInfo { public bool IsImplicit { get; set; } public SequenceStyle Style { get; set; } public SequenceStartEventInfo(IObjectDescriptor source) : base(source) { } } public sealed class SequenceEndEventInfo : EventInfo { public SequenceEndEventInfo(IObjectDescriptor source) : base(source) { } } public interface IAliasProvider { AnchorName GetAlias(object target); } public interface IDeserializer { T Deserialize<T>(string input); T Deserialize<T>(TextReader input); T Deserialize<T>(IParser parser); object? Deserialize(string input); object? Deserialize(TextReader input); object? Deserialize(IParser parser); object? Deserialize(string input, Type type); object? Deserialize(TextReader input, Type type); object? Deserialize(IParser parser, Type type); } public interface IEventEmitter { void Emit(AliasEventInfo eventInfo, IEmitter emitter); void Emit(ScalarEventInfo eventInfo, IEmitter emitter); void Emit(MappingStartEventInfo eventInfo, IEmitter emitter); void Emit(MappingEndEventInfo eventInfo, IEmitter emitter); void Emit(SequenceStartEventInfo eventInfo, IEmitter emitter); void Emit(SequenceEndEventInfo eventInfo, IEmitter emitter); } public interface INamingConvention { string Apply(string value); string Reverse(string value); } public interface INodeDeserializer { bool Deserialize(IParser reader, Type expectedType, Func<IParser, Type, object?> nestedObjectDeserializer, out object? value, ObjectDeserializer rootDeserializer); } public interface INodeTypeResolver { bool Resolve(NodeEvent? nodeEvent, ref Type currentType); } public interface IObjectAccessor { void Set(string name, object target, object value); object? Read(string name, object target); } public interface IObjectDescriptor { object? Value { get; } Type Type { get; } Type StaticType { get; } ScalarStyle ScalarStyle { get; } } public static class ObjectDescriptorExtensions { public static object NonNullValue(this IObjectDescriptor objectDescriptor) { return objectDescriptor.Value ?? throw new InvalidOperationException("Attempted to use a IObjectDescriptor of type '" + objectDescriptor.Type.FullName + "' whose Value is null at a point whete it is invalid to do so. This may indicate a bug in YamlDotNet."); } } public interface IObjectFactory { object Create(Type type); object? CreatePrimitive(Type type); bool GetDictionary(IObjectDescriptor descriptor, out IDictionary? dictionary, out Type[]? genericArguments); Type GetValueType(Type type); void ExecuteOnDeserializing(object value); void ExecuteOnDeserialized(object value); void ExecuteOnSerializing(object value); void ExecuteOnSerialized(object value); } public interface IObjectGraphTraversalStrategy { void Traverse<TContext>(IObjectDescriptor graph, IObjectGraphVisitor<TContext> visitor, TContext context, ObjectSerializer serializer); } public interface IObjectGraphVisitor<TContext> { bool Enter(IPropertyDescriptor? propertyDescriptor, IObjectDescriptor value, TContext context, ObjectSerializer serializer); bool EnterMapping(IObjectDescriptor key, IObjectDescriptor value, TContext context, ObjectSerializer serializer); bool EnterMapping(IPropertyDescriptor key, IObjectDescriptor value, TContext context, ObjectSerializer serializer); void VisitScalar(IObjectDescriptor scalar, TContext context, ObjectSerializer serializer); void VisitMappingStart(IObjectDescriptor mapping, Type keyType, Type valueType, TContext context, ObjectSerializer serializer); void VisitMappingEnd(IObjectDescriptor mapping, TContext context, ObjectSerializer serializer); void VisitSequenceStart(IObjectDescriptor sequence, Type elementType, TContext context, ObjectSerializer serializer); void VisitSequenceEnd(IObjectDescriptor sequence, TContext context, ObjectSerializer serializer); } public interface IPropertyDescriptor { string Name { get; } bool AllowNulls { get; } bool CanWrite { get; } Type Type { get; } Type? TypeOverride { get; set; } int Order { get; set; } ScalarStyle ScalarStyle { get; set; } bool Required { get; } Type? ConverterType { get; } T? GetCustomAttribute<T>() where T : Attribute; IObjectDescriptor Read(object target); void Write(object target, object? value); } public interface IRegistrationLocationSelectionSyntax<TBaseRegistrationType> { void InsteadOf<TRegistrationType>() where TRegistrationType : TBaseRegistrationType; void Before<TRegistrationType>() where TRegistrationType : TBaseRegistrationType; void After<TRegistrationType>() where TRegistrationType : TBaseRegistrationType; void OnTop(); void OnBottom(); } public interface ITrackingRegistrationLocationSelectionSyntax<TBaseRegistrationType> { void InsteadOf<TRegistrationType>() where TRegistrationType : TBaseRegistrationType; } public interface ISerializer { string Serialize(object? graph); string Serialize(object? graph, Type type); void Serialize(TextWriter writer, object? graph); void Serialize(TextWriter writer, object? graph, Type type); void Serialize(IEmitter emitter, object? graph); void Serialize(IEmitter emitter, object? graph, Type type); } public interface ITypeInspector { IEnumerable<IPropertyDescriptor> GetProperties(Type type, object? container); IPropertyDescriptor GetProperty(Type type, object? container, string name, [MaybeNullWhen(true)] bool ignoreUnmatched, bool caseInsensitivePropertyMatching); string GetEnumName(Type enumType, string name); string GetEnumValue(object enumValue); } public interface ITypeResolver { Type Resolve(Type staticType, object? actualValue); } public interface IValueDeserializer { object? DeserializeValue(IParser parser, Type expectedType, SerializerState state, IValueDeserializer nestedObjectDeserializer); } public interface IValuePromise { event Action<object?> ValueAvailable; } public interface IValueSerializer { void SerializeValue(IEmitter emitter, object? value, Type? type); } public interface IYamlConvertible { void Read(IParser parser, Type expectedType, ObjectDeserializer nestedObjectDeserializer); void Write(IEmitter emitter, ObjectSerializer nestedObjectSerializer); } public delegate object? ObjectDeserializer(Type type); public delegate void ObjectSerializer(object? value, Type? type = null); [Obsolete("Please use IYamlConvertible instead")] public interface IYamlSerializable { void ReadYaml(IParser parser); void WriteYaml(IEmitter emitter); } public interface IYamlTypeConverter { bool Accepts(Type type); object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer); void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer); } internal sealed class LazyComponentRegistrationList<TArgument, TComponent> : IEnumerable<Func<TArgument, TComponent>>, IEnumerable { public sealed class LazyComponentRegistration { public readonly Type ComponentType; public readonly Func<TArgument, TComponent> Factory; public LazyComponentRegistration(Type componentType, Func<TArgument, TComponent> factory) { ComponentType = componentType; Factory = factory; } } public sealed class TrackingLazyComponentRegistration { public readonly Type ComponentType; public readonly Func<TComponent, TArgument, TComponent> Factory; public TrackingLazyComponentRegistration(Type componentType, Func<TComponent, TArgument, TComponent> factory) { ComponentType = componentType; Factory = factory; } } private class RegistrationLocationSelector : IRegistrationLocationSelectionSyntax<TComponent> { private readonly LazyComponentRegistrationList<TArgument, TComponent> registrations; private readonly LazyComponentRegistration newRegistration; public RegistrationLocationSelector(LazyComponentRegistrationList<TArgument, TComponent> registrations, LazyComponentRegistration newRegistration) { this.registrations = registrations; this.newRegistration = newRegistration; } void IRegistrationLocationSelectionSyntax<TComponent>.InsteadOf<TRegistrationType>() { if (newRegistration.ComponentType != typeof(TRegistrationType)) { registrations.EnsureNoDuplicateRegistrationType(newRegistration.ComponentType); } int index = registrations.EnsureRegistrationExists<TRegistrationType>(); registrations.entries[index] = newRegistration; } void IRegistrationLocationSelectionSyntax<TComponent>.After<TRegistrationType>() { registrations.EnsureNoDuplicateRegistrationType(newRegistration.ComponentType); int num = registrations.EnsureRegistrationExists<TRegistrationType>(); registrations.entries.Insert(num + 1, newRegistration); } void IRegistrationLocationSelectionSyntax<TComponent>.Before<TRegistrationType>() { registrations.EnsureNoDuplicateRegistrationType(newRegistration.ComponentType); int index = registrations.EnsureRegistrationExists<TRegistrationType>(); registrations.entries.Insert(index, newRegistration); } void IRegistrationLocationSelectionSyntax<TComponent>.OnBottom() { registrations.EnsureNoDuplicateRegistrationType(newRegistration.ComponentType); registrations.entries.Add(newRegistration); } void IRegistrationLocationSelectionSyntax<TComponent>.OnTop() { registrations.EnsureNoDuplicateRegistrationType(newRegistration.ComponentType); registrations.entries.Insert(0, newRegistration); } } private class TrackingRegistrationLocationSelector : ITrackingRegistrationLocationSelectionSyntax<TComponent> { private readonly LazyComponentRegistrationList<TArgument, TComponent> registrations; private readonly TrackingLazyComponentRegistration newRegistration; public TrackingRegistrationLocationSelector(LazyComponentRegistrationList<TArgument, TComponent> registrations, TrackingLazyComponentRegistration newRegistration) { this.registrations = registrations; this.newRegistration = newRegistration; } void ITrackingRegistrationLocationSelectionSyntax<TComponent>.InsteadOf<TRegistrationType>() { if (newRegistration.ComponentType != typeof(TRegistrationType)) { registrations.EnsureNoDuplicateRegistrationType(newRegistration.ComponentType); } int index = registrations.EnsureRegistrationExists<TRegistrationType>(); Func<TArgument, TComponent> innerComponentFactory = registrations.entries[index].Factory; registrations.entries[index] = new LazyComponentRegistration(newRegistration.ComponentType, (TArgument arg) => newRegistration.Factory(innerComponentFactory(arg), arg)); } } private readonly List<LazyComponentRegistration> entries = new List<LazyComponentRegistration>(); public int Count => entries.Count; public IEnumerable<Func<TArgument, TComponent>> InReverseOrder { get { int i = entries.Count - 1; while (i >= 0) { yield return entries[i].Factory; int num = i - 1; i = num; } } } public LazyComponentRegistrationList<TArgument, TComponent> Clone() { LazyComponentRegistrationList<TArgument, TComponent> lazyComponentRegistrationList = new LazyComponentRegistrationList<TArgument, TComponent>(); foreach (LazyComponentRegistration entry in entries) { lazyComponentRegistrationList.entries.Add(entry); } return lazyComponentRegistrationList; } public void Clear() { entries.Clear(); } public void Add(Type componentType, Func<TArgument, TComponent> factory) { entries.Add(new LazyComponentRegistration(componentType, factory)); } public void Remove(Type componentType) { for (int i = 0; i < entries.Count; i++) { if (entries[i].ComponentType == componentType) { entries.RemoveAt(i); return; } } throw new KeyNotFoundException("A component registration of type '" + componentType.FullName + "' was not found."); } public IRegistrationLocationSelectionSyntax<TComponent> CreateRegistrationLocationSelector(Type componentType, Func<TArgument, TComponent> factory) { return new RegistrationLocationSelector(this, new LazyComponentRegistration(componentType, factory)); } public ITrackingRegistrationLocationSelectionSyntax<TComponent> CreateTrackingRegistrationLocationSelector(Type componentType, Func<TComponent, TArgument, TComponent> factory) { return new TrackingRegistrationLocationSelector(this, new TrackingLazyComponentRegistration(componentType, factory)); } public IEnumerator<Func<TArgument, TComponent>> GetEnumerator() { return entries.Select((LazyComponentRegistration e) => e.Factory).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private int IndexOfRegistration(Type registrationType) { for (int i = 0; i < entries.Count; i++) { if (registrationType == entries[i].ComponentType) { return i; } } return -1; } private void EnsureNoDuplicateRegistrationType(Type componentType) { if (IndexOfRegistration(componentType) != -1) { throw new InvalidOperationException("A component of type '" + componentType.FullName + "' has already been registered."); } } private int EnsureRegistrationExists<TRegistrationType>() { int num = IndexOfRegistration(typeof(TRegistrationType)); if (num == -1) { throw new InvalidOperationException("A component of type '" + typeof(TRegistrationType).FullName + "' has not been registered."); } return num; } } internal static class LazyComponentRegistrationListExtensions { public static TComponent BuildComponentChain<TComponent>(this LazyComponentRegistrationList<TComponent, TComponent> registrations, TComponent innerComponent) { return registrations.InReverseOrder.Aggregate(innerComponent, (TComponent inner, Func<TComponent, TComponent> factory) => factory(inner)); } public static TComponent BuildComponentChain<TArgument, TComponent>(this LazyComponentRegistrationList<TArgument, TComponent> registrations, TComponent innerComponent, Func<TComponent, TArgument> argumentBuilder) { Func<TComponent, TArgument> argumentBuilder2 = argumentBuilder; return registrations.InReverseOrder.Aggregate(innerComponent, (TComponent inner, Func<TArgument, TComponent> factory) => factory(argumentBuilder2(inner))); } public static List<TComponent> BuildComponentList<TComponent>(this LazyComponentRegistrationList<Nothing, TComponent> registrations) { return registrations.Select((Func<Nothing, TComponent> factory) => factory(default(Nothing))).ToList(); } public static List<TComponent> BuildComponentList<TArgument, TComponent>(this LazyComponentRegistrationList<TArgument, TComponent> registrations, TArgument argument) { TArgument argument2 = argument; return registrations.Select((Func<TArgument, TComponent> factory) => factory(argument2)).ToList(); } } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct Nothing { } public sealed class ObjectDescriptor : IObjectDescriptor { public object? Value { get; private set; } public Type Type { get; private set; } public Type StaticType { get; private set; } public ScalarStyle ScalarStyle { get; private set; } public ObjectDescriptor(object? value, Type type, Type staticType) : this(value, type, staticType, ScalarStyle.Any) { } public ObjectDescriptor(object? value, Type type, Type staticType, ScalarStyle scalarStyle) { Value = value; Type = type ?? throw new ArgumentNullException("type"); StaticType = staticType ?? throw new ArgumentNullException("staticType"); ScalarStyle = scalarStyle; } } public delegate IObjectGraphTraversalStrategy ObjectGraphTraversalStrategyFactory(ITypeInspector typeInspector, ITypeResolver typeResolver, IEnumerable<IYamlTypeConverter> typeConverters, int maximumRecursion); public sealed class PropertyDescriptor : IPropertyDescriptor { private readonly IPropertyDescriptor baseDescriptor; public bool AllowNulls => baseDescriptor.AllowNulls; public string Name { get; set; } public bool Required => baseDescriptor.Required; public Type Type => baseDescriptor.Type; public Type? TypeOverride { get { return baseDescriptor.TypeOverride; } set { baseDescriptor.TypeOverride = value; } } public Type? ConverterType => baseDescriptor.ConverterType; public int Order { get; set; } public ScalarStyle ScalarStyle { get { return baseDescriptor.ScalarStyle; } set { baseDescriptor.ScalarStyle = value; } } public bool CanWrite => baseDescriptor.CanWrite; public PropertyDescriptor(IPropertyDescriptor baseDescriptor) { this.baseDescriptor = baseDescriptor; Name = baseDescriptor.Name; } public void Write(object target, object? value) { baseDescriptor.Write(target, value); } public T? GetCustomAttribute<T>() where T : Attribute { return baseDescriptor.GetCustomAttribute<T>(); } public IObjectDescriptor Read(object target) { return baseDescriptor.Read(target); } } public sealed class Serializer : ISerializer { private readonly IValueSerializer valueSerializer; private readonly EmitterSettings emitterSettings; public Serializer() : this(new SerializerBuilder().BuildValueSerializer(), EmitterSettings.Default) { } private Serializer(IValueSerializer valueSerializer, EmitterSettings emitterSettings) { this.valueSerializer = valueSerializer ?? throw new ArgumentNullException("valueSerializer"); this.emitterSettings = emitterSettings ?? throw new ArgumentNullException("emitterSettings"); } public static Serializer FromValueSerializer(IValueSerializer valueSerializer, EmitterSettings emitterSettings) { return new Serializer(valueSerializer, emitterSettings); } public string Serialize(object? graph) { using StringWriter stringWriter = new StringWriter(); Serialize(stringWriter, graph); return stringWriter.ToString(); } public string Serialize(object? graph, Type type) { using StringWriter stringWriter = new StringWriter(); Serialize(stringWriter, graph, type); return stringWriter.ToString(); } public void Serialize(TextWriter writer, object? graph) { Serialize(new Emitter(writer, emitterSettings), graph); } public void Serialize(TextWriter writer, object? graph, Type type) { Serialize(new Emitter(writer, emitterSettings), graph, type); } public void Serialize(IEmitter emitter, object? graph) { if (emitter == null) { throw new ArgumentNullException("emitter"); } EmitDocument(emitter, graph, null); } public void Serialize(IEmitter emitter, object? graph, Type type) { if (emitter == null) { throw new ArgumentNullException("emitter"); } if (type == null) { throw new ArgumentNullException("type"); } EmitDocument(emitter, graph, type); } private void EmitDocument(IEmitter emitter, object? graph, Type? type) { emitter.Emit(new YamlDotNet.Core.Events.StreamStart()); emitter.Emit(new YamlDotNet.Core.Events.DocumentStart()); valueSerializer.SerializeValue(emitter, graph, type); emitter.Emit(new YamlDotNet.Core.Events.DocumentEnd(isImplicit: true)); emitter.Emit(new YamlDotNet.Core.Events.StreamEnd()); } } public sealed class SerializerBuilder : BuilderSkeleton<SerializerBuilder> { private class ValueSerializer : IValueSerializer { private readonly IObjectGraphTraversalStrategy traversalStrategy; private readonly IEventEmitter eventEmitter; private readonly IEnumerable<IYamlTypeConverter> typeConverters; private readonly LazyComponentRegistrationList<IEnumerable<IYamlTypeConverter>, IObjectGraphVisitor<Nothing>> preProcessingPhaseObjectGraphVisitorFactories; private readonly LazyComponentRegistrationList<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>> emissionPhaseObjectGraphVisitorFactories; public ValueSerializer(IObjectGraphTraversalStrategy traversalStrategy, IEventEmitter eventEmitter, IEnumerable<IYamlTypeConverter> typeConverters, LazyComponentRegistrationList<IEnumerable<IYamlTypeConverter>, IObjectGraphVisitor<Nothing>> preProcessingPhaseObjectGraphVisitorFactories, LazyComponentRegistrationList<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>> emissionPhaseObjectGraphVisitorFactories) { this.traversalStrategy = traversalStrategy; this.eventEmitter = eventEmitter; this.typeConverters = typeConverters; this.preProcessingPhaseObjectGraphVisitorFactories = preProcessingPhaseObjectGraphVisitorFactories; this.emissionPhaseObjectGraphVisitorFactories = emissionPhaseObjectGraphVisitorFactories; } public void SerializeValue(IEmitter emitter, object? value, Type? type) { IEmitter emitter2 = emitter; Type type2 = type ?? ((value != null) ? value.GetType() : typeof(object)); Type staticType = type ?? typeof(object); ObjectDescriptor graph = new ObjectDescriptor(value, type2, staticType); List<IObjectGraphVisitor<Nothing>> preProcessingPhaseObjectGraphVisitors = preProcessingPhaseObjectGraphVisitorFactories.BuildComponentList(typeConverters); IObjectGraphVisitor<IEmitter> visitor = emissionPhaseObjectGraphVisitorFactories.BuildComponentChain<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>>(new EmittingObjectGraphVisitor(eventEmitter), (IObjectGraphVisitor<IEmitter> inner) => new EmissionPhaseObjectGraphVisitorArgs(inner, eventEmitter, preProcessingPhaseObjectGraphVisitors, typeConverters, NestedObjectSerializer)); foreach (IObjectGraphVisitor<Nothing> item in preProcessingPhaseObjectGraphVisitors) { traversalStrategy.Traverse(graph, item, default(Nothing), NestedObjectSerializer); } traversalStrategy.Traverse(graph, visitor, emitter2, NestedObjectSerializer); void NestedObjectSerializer(object? v, Type? t) { SerializeValue(emitter2, v, t); } } } private ObjectGraphTraversalStrategyFactory objectGraphTraversalStrategyFactory; private readonly LazyComponentRegistrationList<IEnumerable<IYamlTypeConverter>, IObjectGraphVisitor<Nothing>> preProcessingPhaseObjectGraphVisitorFactories; private readonly LazyComponentRegistrationList<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>> emissionPhaseObjectGraphVisitorFactories; private readonly LazyComponentRegistrationList<IEventEmitter, IEventEmitter> eventEmitterFactories; private readonly Dictionary<Type, TagName> tagMappings = new Dictionary<Type, TagName>(); private readonly IObjectFactory objectFactory; private int maximumRecursion = 50; private EmitterSettings emitterSettings = EmitterSettings.Default; private DefaultValuesHandling defaultValuesHandlingConfiguration; private ScalarStyle defaultScalarStyle; private bool quoteNecessaryStrings; private bool quoteYaml1_1Strings; protected override SerializerBuilder Self => this; public SerializerBuilder() : base((ITypeResolver)new DynamicTypeResolver()) { typeInspectorFactories.Add(typeof(CachedTypeInspector), (ITypeInspector inner) => new CachedTypeInspector(inner)); typeInspectorFactories.Add(typeof(NamingConventionTypeInspector), (ITypeInspector inner) => (!(namingConvention is NullNamingConvention)) ? new NamingConventionTypeInspector(inner, namingConvention) : inner); typeInspectorFactories.Add(typeof(YamlAttributesTypeInspector), (ITypeInspector inner) => new YamlAttributesTypeInspector(inner)); typeInspectorFactories.Add(typeof(YamlAttributeOverridesInspector), (ITypeInspector inner) => (overrides == null) ? inner : new YamlAttributeOverridesInspector(inner, overrides.Clone())); preProcessingPhaseObjectGraphVisitorFactories = new LazyComponentRegistrationList<IEnumerable<IYamlTypeConverter>, IObjectGraphVisitor<Nothing>> { { typeof(AnchorAssigner), (IEnumerable<IYamlTypeConverter> typeConverters) => new AnchorAssigner(typeConverters) } }; emissionPhaseObjectGraphVisitorFactories = new LazyComponentRegistrationList<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>> { { typeof(CustomSerializationObjectGraphVisitor), (EmissionPhaseObjectGraphVisitorArgs args) => new CustomSerializationObjectGraphVisitor(args.InnerVisitor, args.TypeConverters, args.NestedObjectSerializer) }, { typeof(AnchorAssigningObjectGraphVisitor), (EmissionPhaseObjectGraphVisitorArgs args) => new AnchorAssigningObjectGraphVisitor(args.InnerVisitor, args.EventEmitter, args.GetPreProcessingPhaseObjectGraphVisitor<AnchorAssigner>()) }, { typeof(DefaultValuesObjectGraphVisitor), (EmissionPhaseObjectGraphVisitorArgs args) => new DefaultValuesObjectGraphVisitor(defaultValuesHandlingConfiguration, args.InnerVisitor, new DefaultObjectFactory()) }, { typeof(CommentsObjectGraphVisitor), (EmissionPhaseObjectGraphVisitorArgs args) => new CommentsObjectGraphVisitor(args.InnerVisitor) } }; eventEmitterFactories = new LazyComponentRegistrationList<IEventEmitter, IEventEmitter> { { typeof(TypeAssigningEventEmitter), (IEventEmitter inner) => new TypeAssigningEventEmitter(inner, tagMappings, quoteNecessaryStrings, quoteYaml1_1Strings, defaultScalarStyle, yamlFormatter, enumNamingConvention, BuildTypeInspector()) } }; objectFactory = new DefaultObjectFactory(); objectGraphTraversalStrategyFactory = (ITypeInspector typeInspector, ITypeResolver typeResolver, IEnumerable<IYamlTypeConverter> typeConverters, int maximumRecursion) => new FullObjectGraphTraversalStrategy(typeInspector, typeResolver, maximumRecursion, namingConvention, objectFactory); } public SerializerBuilder WithQuotingNecessaryStrings(bool quoteYaml1_1Strings = false) { quoteNecessaryStrings = true; this.quoteYaml1_1Strings = quoteYaml1_1Strings; return this; } public SerializerBuilder WithDefaultScalarStyle(ScalarStyle style) { defaultScalarStyle = style; return this; } public SerializerBuilder WithMaximumRecursion(int maximumRecursion) { if (maximumRecursion <= 0) { throw new ArgumentOutOfRangeException("maximumRecursion", $"The maximum recursion specified ({maximumRecursion}) is invalid. It should be a positive integer."); } this.maximumRecursion = maximumRecursion; return this; } public SerializerBuilder WithEventEmitter<TEventEmitter>(Func<IEventEmitter, TEventEmitter> eventEmitterFactory) where TEventEmitter : IEventEmitter { return WithEventEmitter(eventEmitterFactory, delegate(IRegistrationLocationSelectionSyntax<IEventEmitter> w) { w.OnTop(); }); } public SerializerBuilder WithEventEmitter<TEventEmitter>(Func<IEventEmitter, ITypeInspector, TEventEmitter> eventEmitterFactory) where TEventEmitter : IEventEmitter { return WithEventEmitter(eventEmitterFactory, delegate(IRegistrationLocationSelectionSyntax<IEventEmitter> w) { w.OnTop(); }); } public SerializerBuilder WithEventEmitter<TEventEmitter>(Func<IEventEmitter, TEventEmitter> eventEmitterFactory, Action<IRegistrationLocationSelectionSyntax<IEventEmitter>> where) where TEventEmitter : IEventEmitter { Func<IEventEmitter, TEventEmitter> eventEmitterFactory2 = eventEmitterFactory; return WithEventEmitter((IEventEmitter e, ITypeInspector _) => eventEmitterFactory2(e), where); } public SerializerBuilder WithEventEmitter<TEventEmitter>(Func<IEventEmitter, ITypeInspector, TEventEmitter> eventEmitterFactory, Action<IRegistrationLocationSelectionSyntax<IEventEmitter>> where) where TEventEmitter : IEventEmitter { Func<IEventEmitter, ITypeInspector, TEventEmitter> eventEmitterFactory2 = eventEmitterFactory; if (eventEmitterFactory2 == null) { throw new ArgumentNullException("eventEmitterFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(eventEmitterFactories.CreateRegistrationLocationSelector(typeof(TEventEmitter), (IEventEmitter inner) => eventEmitterFactory2(inner, BuildTypeInspector()))); return Self; } public SerializerBuilder WithEventEmitter<TEventEmitter>(WrapperFactory<IEventEmitter, IEventEmitter, TEventEmitter> eventEmitterFactory, Action<ITrackingRegistrationLocationSelectionSyntax<IEventEmitter>> where) where TEventEmitter : IEventEmitter { WrapperFactory<IEventEmitter, IEventEmitter, TEventEmitter> eventEmitterFactory2 = eventEmitterFactory; if (eventEmitterFactory2 == null) { throw new ArgumentNullException("eventEmitterFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(eventEmitterFactories.CreateTrackingRegistrationLocationSelector(typeof(TEventEmitter), (IEventEmitter wrapped, IEventEmitter inner) => eventEmitterFactory2(wrapped, inner))); return Self; } public SerializerBuilder WithoutEventEmitter<TEventEmitter>() where TEventEmitter : IEventEmitter { return WithoutEventEmitter(typeof(TEventEmitter)); } public SerializerBuilder WithoutEventEmitter(Type eventEmitterType) { if (eventEmitterType == null) { throw new ArgumentNullException("eventEmitterType"); } eventEmitterFactories.Remove(eventEmitterType); return this; } public override SerializerBuilder WithTagMapping(TagName tag, Type type) { if (tag.IsEmpty) { throw new ArgumentException("Non-specific tags cannot be maped"); } if (type == null) { throw new ArgumentNullException("type"); } if (tagMappings.TryGetValue(type, out var value)) { throw new ArgumentException($"Type already has a registered tag '{value}' for type '{type.FullName}'", "type"); } tagMappings.Add(type, tag); return this; } public SerializerBuilder WithoutTagMapping(Type type) { if (type == null) { throw new ArgumentNullException("type"); } if (!tagMappings.Remove(type)) { throw new KeyNotFoundException("Tag for type '" + type.FullName + "' is not registered"); } return this; } public SerializerBuilder EnsureRoundtrip() { objectGraphTraversalStrategyFactory = (ITypeInspector typeInspector, ITypeResolver typeResolver, IEnumerable<IYamlTypeConverter> typeConverters, int maximumRecursion) => new RoundtripObjectGraphTraversalStrategy(typeConverters, typeInspector, typeResolver, maximumRecursion, namingConvention, settings, objectFactory); WithEventEmitter((IEventEmitter inner) => new TypeAssigningEventEmitter(inner, tagMappings, quoteNecessaryStrings, quoteYaml1_1Strings, defaultScalarStyle, yamlFormatter, enumNamingConvention, BuildTypeInspector()), delegate(IRegistrationLocationSelectionSyntax<IEventEmitter> loc) { loc.InsteadOf<TypeAssigningEventEmitter>(); }); return WithTypeInspector((ITypeInspector inner) => new ReadableAndWritablePropertiesTypeInspector(inner), delegate(IRegistrationLocationSelectionSyntax<ITypeInspector> loc) { loc.OnBottom(); }); } public SerializerBuilder DisableAliases() { preProcessingPhaseObjectGraphVisitorFactories.Remove(typeof(AnchorAssigner)); emissionPhaseObjectGraphVisitorFactories.Remove(typeof(AnchorAssigningObjectGraphVisitor)); return this; } [Obsolete("The default behavior is now to always emit default values, thefore calling this method has no effect. This behavior is now controlled by ConfigureDefaultValuesHandling.", true)] public SerializerBuilder EmitDefaults() { return ConfigureDefaultValuesHandling(DefaultValuesHandling.Preserve); } public SerializerBuilder ConfigureDefaultValuesHandling(DefaultValuesHandling configuration) { defaultValuesHandlingConfiguration = configuration; return this; } public SerializerBuilder JsonCompatible() { emitterSettings = emitterSettings.WithMaxSimpleKeyLength(int.MaxValue).WithoutAnchorName().WithUtf16SurrogatePairs(); return WithTypeConverter(new YamlDotNet.Serialization.Converters.GuidConverter(jsonCompatible: true), delegate(IRegistrationLocationSelectionSyntax<IYamlTypeConverter> w) { w.InsteadOf<YamlDotNet.Serialization.Converters.GuidConverter>(); }).WithTypeConverter(new DateTime8601Converter(ScalarStyle.DoubleQuoted)).WithEventEmitter((IEventEmitter inner) => new JsonEventEmitter(inner, yamlFormatter, enumNamingConvention, BuildTypeInspector()), delegate(IRegistrationLocationSelectionSyntax<IEventEmitter> loc) { loc.InsteadOf<TypeAssigningEventEmitter>(); }); } public SerializerBuilder WithNewLine(string newLine) { emitterSettings = emitterSettings.WithNewLine(newLine); return this; } public SerializerBuilder WithPreProcessingPhaseObjectGraphVisitor<TObjectGraphVisitor>(TObjectGraphVisitor objectGraphVisitor) where TObjectGraphVisitor : IObjectGraphVisitor<Nothing> { return WithPreProcessingPhaseObjectGraphVisitor(objectGraphVisitor, delegate(IRegistrationLocationSelectionSyntax<IObjectGraphVisitor<Nothing>> w) { w.OnTop(); }); } public SerializerBuilder WithPreProcessingPhaseObjectGraphVisitor<TObjectGraphVisitor>(Func<IEnumerable<IYamlTypeConverter>, TObjectGraphVisitor> objectGraphVisitorFactory) where TObjectGraphVisitor : IObjectGraphVisitor<Nothing> { return WithPreProcessingPhaseObjectGraphVisitor(objectGraphVisitorFactory, delegate(IRegistrationLocationSelectionSyntax<IObjectGraphVisitor<Nothing>> w) { w.OnTop(); }); } public SerializerBuilder WithPreProcessingPhaseObjectGraphVisitor<TObjectGraphVisitor>(TObjectGraphVisitor objectGraphVisitor, Action<IRegistrationLocationSelectionSyntax<IObjectGraphVisitor<Nothing>>> where) where TObjectGraphVisitor : IObjectGraphVisitor<Nothing> { TObjectGraphVisitor objectGraphVisitor2 = objectGraphVisitor; if (objectGraphVisitor2 == null) { throw new ArgumentNullException("objectGraphVisitor"); } if (where == null) { throw new ArgumentNullException("where"); } where(preProcessingPhaseObjectGraphVisitorFactories.CreateRegistrationLocationSelector(typeof(TObjectGraphVisitor), (IEnumerable<IYamlTypeConverter> _) => objectGraphVisitor2)); return this; } public SerializerBuilder WithPreProcessingPhaseObjectGraphVisitor<TObjectGraphVisitor>(Func<IEnumerable<IYamlTypeConverter>, TObjectGraphVisitor> objectGraphVisitorFactory, Action<IRegistrationLocationSelectionSyntax<IObjectGraphVisitor<Nothing>>> where) where TObjectGraphVisitor : IObjectGraphVisitor<Nothing> { Func<IEnumerable<IYamlTypeConverter>, TObjectGraphVisitor> objectGraphVisitorFactory2 = objectGraphVisitorFactory; if (objectGraphVisitorFactory2 == null) { throw new ArgumentNullException("objectGraphVisitorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(preProcessingPhaseObjectGraphVisitorFactories.CreateRegistrationLocationSelector(typeof(TObjectGraphVisitor), (IEnumerable<IYamlTypeConverter> typeConverters) => objectGraphVisitorFactory2(typeConverters))); return this; } public SerializerBuilder WithPreProcessingPhaseObjectGraphVisitor<TObjectGraphVisitor>(WrapperFactory<IObjectGraphVisitor<Nothing>, TObjectGraphVisitor> objectGraphVisitorFactory, Action<ITrackingRegistrationLocationSelectionSyntax<IObjectGraphVisitor<Nothing>>> where) where TObjectGraphVisitor : IObjectGraphVisitor<Nothing> { WrapperFactory<IObjectGraphVisitor<Nothing>, TObjectGraphVisitor> objectGraphVisitorFactory2 = objectGraphVisitorFactory; if (objectGraphVisitorFactory2 == null) { throw new ArgumentNullException("objectGraphVisitorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(preProcessingPhaseObjectGraphVisitorFactories.CreateTrackingRegistrationLocationSelector(typeof(TObjectGraphVisitor), (IObjectGraphVisitor<Nothing> wrapped, IEnumerable<IYamlTypeConverter> _) => objectGraphVisitorFactory2(wrapped))); return this; } public SerializerBuilder WithPreProcessingPhaseObjectGraphVisitor<TObjectGraphVisitor>(WrapperFactory<IEnumerable<IYamlTypeConverter>, IObjectGraphVisitor<Nothing>, TObjectGraphVisitor> objectGraphVisitorFactory, Action<ITrackingRegistrationLocationSelectionSyntax<IObjectGraphVisitor<Nothing>>> where) where TObjectGraphVisitor : IObjectGraphVisitor<Nothing> { WrapperFactory<IEnumerable<IYamlTypeConverter>, IObjectGraphVisitor<Nothing>, TObjectGraphVisitor> objectGraphVisitorFactory2 = objectGraphVisitorFactory; if (objectGraphVisitorFactory2 == null) { throw new ArgumentNullException("objectGraphVisitorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(preProcessingPhaseObjectGraphVisitorFactories.CreateTrackingRegistrationLocationSelector(typeof(TObjectGraphVisitor), (IObjectGraphVisitor<Nothing> wrapped, IEnumerable<IYamlTypeConverter> typeConverters) => objectGraphVisitorFactory2(wrapped, typeConverters))); return this; } public SerializerBuilder WithoutPreProcessingPhaseObjectGraphVisitor<TObjectGraphVisitor>() where TObjectGraphVisitor : IObjectGraphVisitor<Nothing> { return WithoutPreProcessingPhaseObjectGraphVisitor(typeof(TObjectGraphVisitor)); } public SerializerBuilder WithoutPreProcessingPhaseObjectGraphVisitor(Type objectGraphVisitorType) { if (objectGraphVisitorType == null) { throw new ArgumentNullException("objectGraphVisitorType"); } preProcessingPhaseObjectGraphVisitorFactories.Remove(objectGraphVisitorType); return this; } public SerializerBuilder WithObjectGraphTraversalStrategyFactory(ObjectGraphTraversalStrategyFactory objectGraphTraversalStrategyFactory) { this.objectGraphTraversalStrategyFactory = objectGraphTraversalStrategyFactory; return this; } public SerializerBuilder WithEmissionPhaseObjectGraphVisitor<TObjectGraphVisitor>(Func<EmissionPhaseObjectGraphVisitorArgs, TObjectGraphVisitor> objectGraphVisitorFactory) where TObjectGraphVisitor : IObjectGraphVisitor<IEmitter> { return WithEmissionPhaseObjectGraphVisitor(objectGraphVisitorFactory, delegate(IRegistrationLocationSelectionSyntax<IObjectGraphVisitor<IEmitter>> w) { w.OnTop(); }); } public SerializerBuilder WithEmissionPhaseObjectGraphVisitor<TObjectGraphVisitor>(Func<EmissionPhaseObjectGraphVisitorArgs, TObjectGraphVisitor> objectGraphVisitorFactory, Action<IRegistrationLocationSelectionSyntax<IObjectGraphVisitor<IEmitter>>> where) where TObjectGraphVisitor : IObjectGraphVisitor<IEmitter> { Func<EmissionPhaseObjectGraphVisitorArgs, TObjectGraphVisitor> objectGraphVisitorFactory2 = objectGraphVisitorFactory; if (objectGraphVisitorFactory2 == null) { throw new ArgumentNullException("objectGraphVisitorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(emissionPhaseObjectGraphVisitorFactories.CreateRegistrationLocationSelector(typeof(TObjectGraphVisitor), (EmissionPhaseObjectGraphVisitorArgs args) => objectGraphVisitorFactory2(args))); return this; } public SerializerBuilder WithEmissionPhaseObjectGraphVisitor<TObjectGraphVisitor>(WrapperFactory<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>, TObjectGraphVisitor> objectGraphVisitorFactory, Action<ITrackingRegistrationLocationSelectionSyntax<IObjectGraphVisitor<IEmitter>>> where) where TObjectGraphVisitor : IObjectGraphVisitor<IEmitter> { WrapperFactory<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>, TObjectGraphVisitor> objectGraphVisitorFactory2 = objectGraphVisitorFactory; if (objectGraphVisitorFactory2 == null) { throw new ArgumentNullException("objectGraphVisitorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(emissionPhaseObjectGraphVisitorFactories.CreateTrackingRegistrationLocationSelector(typeof(TObjectGraphVisitor), (IObjectGraphVisitor<IEmitter> wrapped, EmissionPhaseObjectGraphVisitorArgs args) => objectGraphVisitorFactory2(wrapped, args))); return this; } public SerializerBuilder WithoutEmissionPhaseObjectGraphVisitor<TObjectGraphVisitor>() where TObjectGraphVisitor : IObjectGraphVisitor<IEmitter> { return WithoutEmissionPhaseObjectGraphVisitor(typeof(TObjectGraphVisitor)); } public SerializerBuilder WithoutEmissionPhaseObjectGraphVisitor(Type objectGraphVisitorType) { if (objectGraphVisitorType == null) { throw new ArgumentNullException("objectGraphVisitorType"); } emissionPhaseObjectGraphVisitorFactories.Remove(objectGraphVisitorType); return this; } public SerializerBuilder WithIndentedSequences() { emitterSettings = emitterSettings.WithIndentedSequences(); return this; } public ISerializer Build() { if (FsharpHelper.Instance == null) { FsharpHelper.Instance = new DefaultFsharpHelper(); } return Serializer.FromValueSerializer(BuildValueSerializer(), emitterSettings); } public IValueSerializer BuildValueSerializer() { IEnumerable<IYamlTypeConverter> typeConverters = BuildTypeConverters(); ITypeInspector typeInspector = BuildTypeInspector(); IObjectGraphTraversalStrategy traversalStrategy = objectGraphTraversalStrategyFactory(typeInspector, typeResolver, typeConverters, maximumRecursion); IEventEmitter eventEmitter = eventEmitterFactories.BuildComponentChain(new WriterEventEmitter()); return new ValueSerializer(traversalStrategy, eventEmitter, typeConverters, preProcessingPhaseObjectGraphVisitorFactories.Clone(), emissionPhaseObjectGraphVisitorFactories.Clone()); } public ITypeInspector BuildTypeInspector() { ITypeInspector typeInspector = new ReadablePropertiesTypeInspector(typeResolver, includeNonPublicProperties); if (!ignoreFields) { typeInspector = new CompositeTypeInspector(new ReadableFieldsTypeInspector(typeResolver), typeInspector); } return typeInspectorFactories.BuildComponentChain(typeInspector); } } public class Settings { public bool AllowPrivateConstructors { get; set; } } public abstract class StaticBuilderSkeleton<TBuilder> where TBuilder : StaticBuilderSkeleton<TBuilder> { internal INamingConvention namingConvention = NullNamingConvention.Instance; internal INamingConvention enumNamingConvention = NullNamingConvention.Instance; internal ITypeResolver typeResolver; internal readonly LazyComponentRegistrationList<Nothing, IYamlTypeConverter> typeConverterFactories; internal readonly LazyComponentRegistrationList<ITypeInspector, ITypeInspector> typeInspectorFactories; internal bool includeNonPublicProperties; internal Settings settings; internal YamlFormatter yamlFormatter = YamlFormatter.Default; protected abstract TBuilder Self { get; } internal StaticBuilderSkeleton(ITypeResolver typeResolver) { typeConverterFactories = new LazyComponentRegistrationList<Nothing, IYamlTypeConverter> { { typeof(YamlDotNet.Serialization.Converters.GuidConverter), (Nothing _) => new YamlDotNet.Serialization.Converters.GuidConverter(jsonCompatible: false) } }; typeInspectorFactories = new LazyComponentRegistrationList<ITypeInspector, ITypeInspector>(); this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver"); settings = new Settings(); } public TBuilder WithNamingConvention(INamingConvention namingConvention) { this.namingConvention = namingConvention ?? throw new ArgumentNullException("namingConvention"); return Self; } public TBuilder WithEnumNamingConvention(INamingConvention enumNamingConvention) { this.enumNamingConvention = enumNamingConvention ?? throw new ArgumentNullException("enumNamingConvention"); return Self; } public TBuilder WithTypeResolver(ITypeResolver typeResolver) { this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver"); return Self; } public abstract TBuilder WithTagMapping(TagName tag, Type type); public TBuilder WithTypeConverter(IYamlTypeConverter typeConverter) { return WithTypeConverter(typeConverter, delegate(IRegistrationLocationSelectionSyntax<IYamlTypeConverter> w) { w.OnTop(); }); } public TBuilder WithTypeConverter(IYamlTypeConverter typeConverter, Action<IRegistrationLocationSelectionSyntax<IYamlTypeConverter>> where) { IYamlTypeConverter typeConverter2 = typeConverter; if (typeConverter2 == null) { throw new ArgumentNullException("typeConverter"); } if (where == null) { throw new ArgumentNullException("where"); } where(typeConverterFactories.CreateRegistrationLocationSelector(typeConverter2.GetType(), (Nothing _) => typeConverter2)); return Self; } public TBuilder WithTypeConverter<TYamlTypeConverter>(WrapperFactory<IYamlTypeConverter, IYamlTypeConverter> typeConverterFactory, Action<ITrackingRegistrationLocationSelectionSyntax<IYamlTypeConverter>> where) where TYamlTypeConverter : IYamlTypeConverter { WrapperFactory<IYamlTypeConverter, IYamlTypeConverter> typeConverterFactory2 = typeConverterFactory; if (typeConverterFactory2 == null) { throw new ArgumentNullException("typeConverterFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(typeConverterFactories.CreateTrackingRegistrationLocationSelector(typeof(TYamlTypeConverter), (IYamlTypeConverter wrapped, Nothing _) => typeConverterFactory2(wrapped))); return Self; } public TBuilder WithoutTypeConverter<TYamlTypeConverter>() where TYamlTypeConverter : IYamlTypeConverter { return WithoutTypeConverter(typeof(TYamlTypeConverter)); } public TBuilder WithoutTypeConverter(Type converterType) { if (converterType == null) { throw new ArgumentNullException("converterType"); } typeConverterFactories.Remove(converterType); return Self; } public TBuilder WithTypeInspector<TTypeInspector>(Func<ITypeInspector, TTypeInspector> typeInspectorFactory) where TTypeInspector : ITypeInspector { return WithTypeInspector(typeInspectorFactory, delegate(IRegistrationLocationSelectionSyntax<ITypeInspector> w) { w.OnTop(); }); } public TBuilder WithTypeInspector<TTypeInspector>(Func<ITypeInspector, TTypeInspector> typeInspectorFactory, Action<IRegistrationLocationSelectionSyntax<ITypeInspector>> where) where TTypeInspector : ITypeInspector { Func<ITypeInspector, TTypeInspector> typeInspectorFactory2 = typeInspectorFactory; if (typeInspectorFactory2 == null) { throw new ArgumentNullException("typeInspectorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(typeInspectorFactories.CreateRegistrationLocationSelector(typeof(TTypeInspector), (ITypeInspector inner) => typeInspectorFactory2(inner))); return Self; } public TBuilder WithTypeInspector<TTypeInspector>(WrapperFactory<ITypeInspector, ITypeInspector, TTypeInspector> typeInspectorFactory, Action<ITrackingRegistrationLocationSelectionSyntax<ITypeInspector>> where) where TTypeInspector : ITypeInspector { WrapperFactory<ITypeInspector, ITypeInspector, TTypeInspector> typeInspectorFactory2 = typeInspectorFactory; if (typeInspectorFactory2 == null) { throw new ArgumentNullException("typeInspectorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(typeInspectorFactories.CreateTrackingRegistrationLocationSelector(typeof(TTypeInspector), (ITypeInspector wrapped, ITypeInspector inner) => typeInspectorFactory2(wrapped, inner))); return Self; } public TBuilder WithoutTypeInspector<TTypeInspector>() where TTypeInspector : ITypeInspector { return WithoutTypeInspector(typeof(TTypeInspector)); } public TBuilder WithoutTypeInspector(Type inspectorType) { if (inspectorType == null) { throw new ArgumentNullException("inspectorType"); } typeInspectorFactories.Remove(inspectorType); return Self; } public TBuilder WithYamlFormatter(YamlFormatter formatter) { yamlFormatter = formatter ?? throw new ArgumentNullException("formatter"); return Self; } protected IEnumerable<IYamlTypeConverter> BuildTypeConverters() { return typeConverterFactories.BuildComponentList(); } } public abstract class StaticContext { public virtual bool IsKnownType(Type type) { throw new NotImplementedException(); } public virtual ITypeResolver GetTypeResolver() { throw new NotImplementedException(); } public virtual StaticObjectFactory GetFactory() { throw new NotImplementedException(); } public virtual ITypeInspector GetTypeInspector() { throw new NotImplementedException(); } } public sealed class StaticDeserializerBuilder : StaticBuilderSkeleton<StaticDeserializerBuilder> { private readonly StaticContext context; private readonly StaticObjectFactory factory; private readonly LazyComponentRegistrationList<Nothing, INodeDeserializer> nodeDeserializerFactories; private readonly LazyComponentRegistrationList<Nothing, INodeTypeResolver> nodeTypeResolverFactories; private readonly Dictionary<TagName, Type> tagMappings; private readonly ITypeConverter typeConverter; private readonly Dictionary<Type, Type> typeMappings; private bool ignoreUnmatched; private bool duplicateKeyChecking; private bool attemptUnknownTypeDeserialization; private bool enforceNullability; private bool caseInsensitivePropertyMatching; protected override StaticDeserializerBuilder Self => this; public StaticDeserializerBuilder(StaticContext context) : base(context.GetTypeResolver()) { this.context = context; factory = context.GetFactory(); typeMappings = new Dictionary<Type, Type>(); tagMappings = new Dictionary<TagName, Type> { { FailsafeSchema.Tags.Map, typeof(Dictionary<object, object>) }, { FailsafeSchema.Tags.Str, typeof(string) }, { JsonSchema.Tags.Bool, typeof(bool) }, { JsonSchema.Tags.Float, typeof(double) }, { JsonSchema.Tags.Int, typeof(int) }, { DefaultSchema.Tags.Timestamp, typeof(DateTime) } }; typeInspectorFactories.Add(typeof(CachedTypeInspector), (ITypeInspector inner) => new CachedTypeInspector(inner)); typeInspectorFactories.Add(typeof(NamingConventionTypeInspector), (ITypeInspector inner) => (!(namingConvention is NullNamingConvention)) ? new NamingConventionTypeInspector(inner, namingConvention) : inner); typeInspectorFactories.Add(typeof(YamlAttributesTypeInspector), (ITypeInspector inner) => new YamlAttributesTypeInspector(inner)); nodeDeserializerFactories = new LazyComponentRegistrationList<Nothing, INodeDeserializer> { { typeof(YamlConvertibleNodeDeserializer), (Nothing _) => new YamlConvertibleNodeDeserializer(factory) }, { typeof(YamlSerializableNodeDeserializer), (Nothing _) => new YamlSerializableNodeDeserializer(factory) }, { typeof(TypeConverterNodeDeserializer), (Nothing _) => new TypeConverterNodeDeserializer(BuildTypeConverters()) }, { typeof(NullNodeDeserializer), (Nothing _) => new NullNodeDeserializer() }, { typeof(ScalarNodeDeserializer), (Nothing _) => new ScalarNodeDeserializer(attemptUnknownTypeDeserialization, typeConverter, BuildTypeInspector(), yamlFormatter, enumNamingConvention) }, { typeof(StaticArrayNodeDeserializer), (Nothing _) => new StaticArrayNodeDeserializer(factory) }, { typeof(StaticDictionaryNodeDeserializer), (Nothing _) => new StaticDictionaryNodeDeserializer(factory, duplicateKeyChecking) }, { typeof(StaticCollectionNodeDeserializer), (Nothing _) => new StaticCollectionNodeDeserializer(factory) }, { typeof(ObjectNodeDeserializer), (Nothing _) => new ObjectNodeDeserializer(factory, BuildTypeInspector(), ignoreUnmatched, duplicateKeyChecking, typeConverter, enumNamingConvention, enforceNullability, caseInsensitivePropertyMatching, enforceRequiredProperties: false, BuildTypeConverters()) } }; nodeTypeResolverFactories = new LazyComponentRegistrationList<Nothing, INodeTypeResolver> { { typeof(MappingNodeTypeResolver), (Nothing _) => new MappingNodeTypeResolver(typeMappings) }, { typeof(YamlConvertibleTypeResolver), (Nothing _) => new YamlConvertibleTypeResolver() }, { typeof(YamlSerializableTypeResolver), (Nothing _) => new YamlSerializableTypeResolver() }, { typeof(TagNodeTypeResolver), (Nothing _) => new TagNodeTypeResolver(tagMappings) }, { typeof(PreventUnknownTagsNodeTypeResolver), (Nothing _) => new PreventUnknownTagsNodeTypeResolver() }, { typeof(DefaultContainersNodeTypeResolver), (Nothing _) => new DefaultContainersNodeTypeResolver() } }; typeConverter = new NullTypeConverter(); } public ITypeInspector BuildTypeInspector() { ITypeInspector typeInspector = context.GetTypeInspector(); return typeInspectorFactories.BuildComponentChain(typeInspector); } public StaticDeserializerBuilder WithAttemptingUnquotedStringTypeDeserialization() { attemptUnknownTypeDeserialization = true; return this; } public StaticDeserializerBuilder WithNodeDeserializer(INodeDeserializer nodeDeserializer) { return WithNodeDeserializer(nodeDeserializer, delegate(IRegistrationLocationSelectionSyntax<INodeDeserializer> w) { w.OnTop(); }); } public StaticDeserializerBuilder WithNodeDeserializer(INodeDeserializer nodeDeserializer, Action<IRegistrationLocationSelectionSyntax<INodeDeserializer>> where) { INodeDeserializer nodeDeserializer2 = nodeDeserializer; if (nodeDeserializer2 == null) { throw new ArgumentNullException("nodeDeserializer"); } if (where == null) { throw new ArgumentNullException("where"); } where(nodeDeserializerFactories.CreateRegistrationLocationSelector(nodeDeserializer2.GetType(), (Nothing _) => nodeDeserializer2)); return this; } public StaticDeserializerBuilder WithNodeDeserializer<TNodeDeserializer>(WrapperFactory<INodeDeserializer, TNodeDeserializer> nodeDeserializerFactory, Action<ITrackingRegistrationLocationSelectionSyntax<INodeDeserializer>> where) where TNodeDeserializer : INodeDeserializer { WrapperFactory<INodeDeserializer, TNodeDeserializer> nodeDeserializerFactory2 = nodeDeserializerFactory; if (nodeDeserializerFactory2 == null) { throw new ArgumentNullException("nodeDeserializerFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(nodeDeserializerFactories.CreateTrackingRegistrationLocationSelector(typeof(TNodeDeserializer), (INodeDeserializer wrapped, Nothing _) => nodeDeserializerFactory2(wrapped))); return this; } public StaticDeserializerBuilder WithCaseInsensitivePropertyMatching() { caseInsensitivePropertyMatching = true; return this; } public StaticDeserializerBuilder WithEnforceNullability() { enforceNullability = true; return this; } public StaticDeserializerBuilder WithoutNodeDeserializer<TNodeDeserializer>() where TNodeDeserializer : INodeDeserializer { return WithoutNodeDeserializer(typeof(TNodeDeserializer)); } public StaticDeserializerBuilder WithoutNodeDeserializer(Type nodeDeserializerType) { if (nodeDeserializerType == null) { throw new ArgumentNullException("nodeDeserializerType"); } nodeDeserializerFactories.Remove(nodeDeserializerType); return this; } public StaticDeserializerBuilder WithTypeDiscriminatingNodeDeserializer(Action<ITypeDiscriminatingNodeDeserializerOptions> configureTypeDiscriminatingNodeDeserializerOptions, int maxDepth = -1, int maxLength = -1) { TypeDiscriminatingNodeDeserializerOptions typeDiscriminatingNodeDeserializerOptions = new TypeDiscriminatingNodeDeserializerOptions(); configureTypeDiscriminatingNodeDeserializerOptions(typeDiscriminatingNodeDeserializerOptions); TypeDiscriminatingNodeDeserializer nodeDeserializer = new TypeDiscriminatingNodeDeserializer(nodeDeserializerFactories.BuildComponentList(), typeDiscriminatingNodeDeserializerOptions.discriminators, maxDepth, maxLength); return WithNodeDeserializer(nodeDeserializer, delegate(IRegistrationLocationSelectionSyntax<INodeDeserializer> s) { s.Before<DictionaryNodeDeserializer>(); }); } public StaticDeserializerBuilder WithNodeTypeResolver(INodeTypeResolver nodeTypeResolver) { return WithNodeTypeResolver(nodeTypeResolver, delegate(IRegistrationLocationSelectionSyntax<INodeTypeResolver> w) { w.OnTop(); }); } public StaticDeserializerBuilder WithNodeTypeResolver(INodeTypeResolver nodeTypeResolver, Action<IRegistrationLocationSelectionSyntax<INodeTypeResolver>> where) { INodeTypeResolver nodeTypeResolver2 = nodeTypeResolver; if (nodeTypeResolver2 == null) { throw new ArgumentNullException("nodeTypeResolver"); } if (where == null) { throw new ArgumentNullException("where"); } where(nodeTypeResolverFactories.CreateRegistrationLocationSelector(nodeTypeResolver2.GetType(), (Nothing _) => nodeTypeResolver2)); return this; } public StaticDeserializerBuilder WithNodeTypeResolver<TNodeTypeResolver>(WrapperFactory<INodeTypeResolver, TNodeTypeResolver> nodeTypeResolverFactory, Action<ITrackingRegistrationLocationSelectionSyntax<INodeTypeResolver>> where) where TNodeTypeResolver : INodeTypeResolver { WrapperFactory<INodeTypeResolver, TNodeTypeResolver> nodeTypeResolverFactory2 = nodeTypeResolverFactory; if (nodeTypeResolverFactory2 == null) { throw new ArgumentNullException("nodeTypeResolverFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(nodeTypeResolverFactories.CreateTrackingRegistrationLocationSelector(typeof(TNodeTypeResolver), (INodeTypeResolver wrapped, Nothing _) => nodeTypeResolverFactory2(wrapped))); return this; } public StaticDeserializerBuilder WithoutNodeTypeResolver<TNodeTypeResolver>() where TNodeTypeResolver : INodeTypeResolver { return WithoutNodeTypeResolver(typeof(TNodeTypeResolver)); } public StaticDeserializerBuilder WithoutNodeTypeResolver(Type nodeTypeResolverType) { if (nodeTypeResolverType == null) { throw new ArgumentNullException("nodeTypeResolverType"); } nodeTypeResolverFactories.Remove(nodeTypeResolverType); return this; } public override StaticDeserializerBuilder WithTagMapping(TagName tag, Type type) { if (tag.IsEmpty) { throw new ArgumentException("Non-specific tags cannot be maped"); } if (type == null) { throw new ArgumentNullException("type"); } if (tagMappings.TryGetValue(tag, out Type value)) { throw new ArgumentException($"Type already has a registered type '{value.FullName}' for tag '{tag}'", "tag"); } tagMappings.Add(tag, type); return this; } public StaticDeserializerBuilder WithTypeMapping<TInterface, TConcrete>() where TConcrete : TInterface { Type typeFromHandle = typeof(TInterface); Type typeFromHandle2 = typeof(TConcrete); if (!typeFromHandle.IsAssignableFrom(typeFromHandle2)) { throw new InvalidOperationException("The type '" + typeFromHandle2.Name + "' does not implement interface '" + typeFromHandle.Name + "'."); } typeMappings[typeFromHandle] = typeFromHandle2; return this; } public StaticDeserializerBuilder WithoutTagMapping(TagName tag) { if (tag.IsEmpty) { throw new ArgumentException("Non-specific tags cannot be maped"); } if (!tagMappings.Remove(tag)) { throw new KeyNotFoundException($"Tag '{tag}' is not registered"); } return this; } public StaticDeserializerBuilder IgnoreUnmatchedProperties() { ignoreUnmatched = true; return this; } public StaticDeserializerBuilder WithDuplicateKeyChecking() { duplicateKeyChecking = true; return this; } public IDeserializer Build() { return Deserializer.FromValueDeserializer(BuildValueDeserializer()); } public IValueDeserializer BuildValueDeserializer() { return new AliasValueDeserializer(new NodeValueDeserializer(nodeDeserializerFactories.BuildComponentList(), nodeTypeResolverFactories.BuildComponentList(), typeConverter, enumNamingConvention, BuildTypeInspector())); } } public sealed class StaticSerializerBuilder : StaticBuilderSkeleton<StaticSerializerBuilder> { private class ValueSerializer : IValueSerializer { private readonly IObjectGraphTraversalStrategy traversalStrategy; private readonly IEventEmitter eventEmitter; private readonly IEnumerable<IYamlTypeConverter> typeConverters; private readonly LazyComponentRegistrationList<IEnumerable<IYamlTypeConverter>, IObjectGraphVisitor<Nothing>> preProcessingPhaseObjectGraphVisitorFactories; private readonly LazyComponentRegistrationList<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>> emissionPhaseObjectGraphVisitorFactories; public ValueSerializer(IObjectGraphTraversalStrategy traversalStrategy, IEventEmitter eventEmitter, IEnumerable<IYamlTypeConverter> typeConverters, LazyComponentRegistrationList<IEnumerable<IYamlTypeConverter>, IObjectGraphVisitor<Nothing>> preProcessingPhaseObjectGraphVisitorFactories, LazyComponentRegistrationList<EmissionPhaseObjectGraphVisitorArgs, IObjectGraphVisitor<IEmitter>> emissionPhaseObjectGraphVisitorFactories) { this.traversalStrategy = traversalStrategy; this.eventEmitter = eventEmitter; this.typeConverters = typeConverters; this.preProcessingPhaseObjectGraphVisitorFactories = preProcessingPhaseObjectGraphVisitorFactories; this.emissionPhaseObjectGraphVisitorFactories = emissionPhaseObjectGraphVisitorFactories; } public void SerializeValue(IEmitter emitter, object? value, Type? type) { IEmitter emitter2 =