/* Copyright (C) 2014-2019 de4dot@gmail.com This file is part of dnSpy dnSpy is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. dnSpy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with dnSpy. If not, see . */ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Threading; using dnlib.DotNet.Resources; using dnSpy.Contracts.Images; using dnSpy.Contracts.TreeView; namespace dnSpy.Contracts.Documents.TreeView.Resources { /// /// Serialized resource element node base class /// public abstract class SerializedResourceElementNode : ResourceElementNode { object? deserializedData; string? DeserializedStringValue => deserializedData?.ToString(); bool IsSerialized => deserializedData is null; /// protected override string ValueString { get { if (deserializedData is null) return base.ValueString; return ConvertObjectToString(deserializedData)!; } } /// protected override ImageReference GetIcon() => DsImages.UserDefinedDataType; /// /// Constructor /// /// Treenode group /// Resource element protected SerializedResourceElementNode(ITreeNodeGroup treeNodeGroup, ResourceElement resourceElement) : base(treeNodeGroup, resourceElement) => Debug.Assert(resourceElement.ResourceData is BinaryResourceData); /// public override void Initialize() => DeserializeIfPossible(); void DeserializeIfPossible() { if (Context.DeserializeResources) Deserialize(); } /// protected override IEnumerable GetDeserializedData() { var dd = deserializedData; var re = ResourceElement; if (dd is not null) yield return new ResourceData(re.Name, token => ResourceUtilities.StringToStream(ConvertObjectToString(dd))); else yield return new ResourceData(re.Name, token => new MemoryStream(((BinaryResourceData)re.ResourceData).Data)); } /// /// Called after it's been deserialized /// protected virtual void OnDeserialized() { } /// /// true if can execute /// public bool CanDeserialize => IsSerialized; /// /// Deserializes the data /// public void Deserialize() { if (!CanDeserialize) return; var serializedData = ((BinaryResourceData)ResourceElement.ResourceData).Data; var formatter = new BinaryFormatter(); try { #pragma warning disable SYSLIB0011 deserializedData = formatter.Deserialize(new MemoryStream(serializedData)); #pragma warning restore SYSLIB0011 } catch { return; } if (deserializedData is null) return; try { OnDeserialized(); } catch { deserializedData = null; } } string? ConvertObjectToString(object obj) { if (obj is null) return null; if (!Context.DeserializeResources) return obj.ToString(); return SerializationUtilities.ConvertObjectToString(obj); } /// public override void UpdateData(ResourceElement newResElem) { base.UpdateData(newResElem); deserializedData = null; DeserializeIfPossible(); } /// public override string? ToString(CancellationToken token, bool canDecompile) { if (IsSerialized) return null; return DeserializedStringValue; } } }