2020-03-26 12:28:03 +00:00
|
|
|
|
using System;
|
2020-04-20 21:36:33 +00:00
|
|
|
|
using System.Collections.Concurrent;
|
2020-03-26 12:28:03 +00:00
|
|
|
|
using System.Collections.Generic;
|
2020-06-26 17:33:38 +00:00
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
2020-03-26 12:28:03 +00:00
|
|
|
|
using System.IO;
|
2020-04-06 20:48:54 +00:00
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Reflection;
|
2020-03-26 12:28:03 +00:00
|
|
|
|
using System.Text;
|
2020-05-25 16:24:16 +00:00
|
|
|
|
using System.Threading.Tasks;
|
2020-03-26 12:28:03 +00:00
|
|
|
|
using Newtonsoft.Json;
|
2020-04-06 20:48:54 +00:00
|
|
|
|
using Newtonsoft.Json.Serialization;
|
|
|
|
|
using Wabbajack.Common.Serialization.Json;
|
2020-03-26 12:28:03 +00:00
|
|
|
|
using File = Alphaleonis.Win32.Filesystem.File;
|
2020-04-24 13:05:22 +00:00
|
|
|
|
using Path = Alphaleonis.Win32.Filesystem.Path;
|
2020-03-26 12:28:03 +00:00
|
|
|
|
|
|
|
|
|
namespace Wabbajack.Common
|
|
|
|
|
{
|
|
|
|
|
public static partial class Utils
|
|
|
|
|
{
|
|
|
|
|
public static List<JsonConverter> Converters = new List<JsonConverter>
|
|
|
|
|
{
|
|
|
|
|
new HashJsonConverter(),
|
|
|
|
|
new RelativePathConverter(),
|
2020-04-12 16:06:37 +00:00
|
|
|
|
new AbsolutePathConverter(),
|
2020-03-26 12:28:03 +00:00
|
|
|
|
new HashRelativePathConverter(),
|
2020-04-01 12:17:38 +00:00
|
|
|
|
new FullPathConverter(),
|
2020-04-01 19:15:23 +00:00
|
|
|
|
new GameConverter(),
|
|
|
|
|
new PercentConverter(),
|
2020-04-24 13:05:22 +00:00
|
|
|
|
new IPathConverter(),
|
2020-03-26 12:28:03 +00:00
|
|
|
|
};
|
2020-04-06 20:48:54 +00:00
|
|
|
|
|
|
|
|
|
public static JsonSerializerSettings JsonSettings =>
|
2020-04-11 03:16:10 +00:00
|
|
|
|
new JsonSerializerSettings {
|
|
|
|
|
TypeNameHandling = TypeNameHandling.Objects,
|
|
|
|
|
SerializationBinder = new JsonNameSerializationBinder(),
|
2020-05-14 23:50:02 +00:00
|
|
|
|
Converters = Converters,
|
|
|
|
|
DateTimeZoneHandling = DateTimeZoneHandling.Utc
|
|
|
|
|
};
|
2020-11-03 01:55:54 +00:00
|
|
|
|
|
|
|
|
|
public static JsonSerializerSettings JsonSettingsPretty =>
|
|
|
|
|
new JsonSerializerSettings {
|
|
|
|
|
TypeNameHandling = TypeNameHandling.Objects,
|
|
|
|
|
SerializationBinder = new JsonNameSerializationBinder(),
|
|
|
|
|
Converters = Converters,
|
|
|
|
|
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
|
|
|
|
|
Formatting = Formatting.Indented
|
|
|
|
|
};
|
2020-04-11 03:16:10 +00:00
|
|
|
|
|
|
|
|
|
public static JsonSerializerSettings GenericJsonSettings =>
|
2020-05-14 23:50:02 +00:00
|
|
|
|
new JsonSerializerSettings
|
|
|
|
|
{
|
|
|
|
|
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
|
|
|
|
|
};
|
2020-04-11 03:16:10 +00:00
|
|
|
|
|
2020-04-01 12:17:38 +00:00
|
|
|
|
|
2020-04-06 20:48:54 +00:00
|
|
|
|
public static void ToJson<T>(this T obj, string filename)
|
2020-03-26 12:28:03 +00:00
|
|
|
|
{
|
|
|
|
|
if (File.Exists(filename))
|
|
|
|
|
File.Delete(filename);
|
2020-04-06 20:48:54 +00:00
|
|
|
|
File.WriteAllText(filename, JsonConvert.SerializeObject(obj, Formatting.Indented, JsonSettings));
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-03 01:55:54 +00:00
|
|
|
|
public static void ToJson<T>(this T obj, Stream stream, bool useGenericSettings = false, bool prettyPrint = false)
|
2020-04-06 20:48:54 +00:00
|
|
|
|
{
|
2021-03-19 22:37:58 +00:00
|
|
|
|
using var tw = new StreamWriter(stream, new UTF8Encoding(false), bufferSize: 1024, leaveOpen: true);
|
2020-04-06 20:48:54 +00:00
|
|
|
|
using var writer = new JsonTextWriter(tw);
|
2020-11-03 01:55:54 +00:00
|
|
|
|
|
2021-07-19 22:15:27 +00:00
|
|
|
|
JsonSerializerSettings settings = SettingsForOptions(useGenericSettings, prettyPrint);
|
|
|
|
|
|
|
|
|
|
var ser = JsonSerializer.Create(settings);
|
|
|
|
|
ser.Serialize(writer, obj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static JsonSerializerSettings SettingsForOptions(bool useGenericSettings, bool prettyPrint)
|
|
|
|
|
{
|
|
|
|
|
return (useGenericSettings, prettyPrint) switch
|
2020-11-03 01:55:54 +00:00
|
|
|
|
{
|
|
|
|
|
(true, true) => GenericJsonSettings,
|
|
|
|
|
(false, true) => JsonSettingsPretty,
|
|
|
|
|
(false, false) => JsonSettings,
|
|
|
|
|
(true, false) => GenericJsonSettings
|
|
|
|
|
};
|
2020-03-26 12:28:03 +00:00
|
|
|
|
}
|
2021-07-19 22:15:27 +00:00
|
|
|
|
|
2020-11-03 01:55:54 +00:00
|
|
|
|
public static async ValueTask ToJsonAsync<T>(this T obj, AbsolutePath path, bool useGenericSettings = false, bool prettyPrint = false)
|
2020-04-08 04:19:36 +00:00
|
|
|
|
{
|
2020-05-25 16:24:16 +00:00
|
|
|
|
await using var fs = await path.Create();
|
2020-11-03 01:55:54 +00:00
|
|
|
|
obj.ToJson(fs, useGenericSettings, prettyPrint: prettyPrint);
|
2020-04-08 04:19:36 +00:00
|
|
|
|
}
|
2020-03-26 12:28:03 +00:00
|
|
|
|
|
2021-07-19 22:15:27 +00:00
|
|
|
|
public static string ToJson<T>(this T obj, bool useGenericSettings = false, bool prettyPrint = false)
|
2020-03-26 12:28:03 +00:00
|
|
|
|
{
|
2021-07-19 22:15:27 +00:00
|
|
|
|
return JsonConvert.SerializeObject(obj, SettingsForOptions(useGenericSettings, prettyPrint));
|
2020-03-26 12:28:03 +00:00
|
|
|
|
}
|
2020-04-01 12:17:38 +00:00
|
|
|
|
|
2020-04-09 17:12:33 +00:00
|
|
|
|
public static T FromJson<T>(this AbsolutePath filename)
|
2020-03-26 12:28:03 +00:00
|
|
|
|
{
|
2020-04-06 20:48:54 +00:00
|
|
|
|
return JsonConvert.DeserializeObject<T>(filename.ReadAllText(), JsonSettings)!;
|
2020-03-26 12:28:03 +00:00
|
|
|
|
}
|
2020-04-01 12:17:38 +00:00
|
|
|
|
|
2021-03-19 22:37:58 +00:00
|
|
|
|
|
|
|
|
|
public static async Task<T> FromJsonAsync<T>(this AbsolutePath filename)
|
|
|
|
|
{
|
|
|
|
|
return JsonConvert.DeserializeObject<T>(await filename.ReadAllTextAsync(), JsonSettings)!;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-09 17:12:33 +00:00
|
|
|
|
public static T FromJsonString<T>(this string data)
|
2020-03-26 12:28:03 +00:00
|
|
|
|
{
|
2020-04-06 20:48:54 +00:00
|
|
|
|
return JsonConvert.DeserializeObject<T>(data, JsonSettings)!;
|
2020-03-26 12:28:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-11 03:16:10 +00:00
|
|
|
|
public static T FromJson<T>(this Stream stream, bool genericReader = false)
|
2020-03-26 12:28:03 +00:00
|
|
|
|
{
|
2020-06-26 17:19:07 +00:00
|
|
|
|
using var tr = new StreamReader(stream, Encoding.UTF8, bufferSize: 1024, detectEncodingFromByteOrderMarks: false, leaveOpen: true);
|
2020-04-06 20:48:54 +00:00
|
|
|
|
using var reader = new JsonTextReader(tr);
|
2020-04-11 03:16:10 +00:00
|
|
|
|
var ser = JsonSerializer.Create(genericReader ? GenericJsonSettings : JsonSettings);
|
2020-04-10 22:35:35 +00:00
|
|
|
|
var result = ser.Deserialize<T>(reader);
|
|
|
|
|
if (result == null)
|
|
|
|
|
throw new JsonException("Type deserialized into null");
|
|
|
|
|
return result;
|
2020-03-26 12:28:03 +00:00
|
|
|
|
}
|
2020-04-01 12:17:38 +00:00
|
|
|
|
|
2020-04-26 13:37:57 +00:00
|
|
|
|
public class HashJsonConverter : JsonConverter<Hash>
|
2020-03-26 12:28:03 +00:00
|
|
|
|
{
|
|
|
|
|
public override void WriteJson(JsonWriter writer, Hash value, JsonSerializer serializer)
|
|
|
|
|
{
|
|
|
|
|
writer.WriteValue(value.ToBase64());
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-01 12:17:38 +00:00
|
|
|
|
public override Hash ReadJson(JsonReader reader, Type objectType, Hash existingValue, bool hasExistingValue,
|
|
|
|
|
JsonSerializer serializer)
|
2020-03-26 12:28:03 +00:00
|
|
|
|
{
|
2020-04-03 23:23:13 +00:00
|
|
|
|
return Hash.FromBase64((string)reader.Value!);
|
2020-03-26 12:28:03 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-06-17 23:09:03 +00:00
|
|
|
|
|
2020-04-26 05:13:42 +00:00
|
|
|
|
public class RelativePathConverter : JsonConverter<RelativePath>
|
2020-03-26 12:28:03 +00:00
|
|
|
|
{
|
|
|
|
|
public override void WriteJson(JsonWriter writer, RelativePath value, JsonSerializer serializer)
|
|
|
|
|
{
|
|
|
|
|
writer.WriteValue((string)value);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-01 12:17:38 +00:00
|
|
|
|
public override RelativePath ReadJson(JsonReader reader, Type objectType, RelativePath existingValue,
|
|
|
|
|
bool hasExistingValue,
|
2020-03-26 12:28:03 +00:00
|
|
|
|
JsonSerializer serializer)
|
|
|
|
|
{
|
2020-04-03 23:23:13 +00:00
|
|
|
|
return (RelativePath)(string)reader.Value!;
|
2020-03-26 12:28:03 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-04-01 12:17:38 +00:00
|
|
|
|
|
2020-04-12 16:06:37 +00:00
|
|
|
|
private class AbsolutePathConverter : JsonConverter<AbsolutePath>
|
2020-03-26 12:28:03 +00:00
|
|
|
|
{
|
|
|
|
|
public override void WriteJson(JsonWriter writer, AbsolutePath value, JsonSerializer serializer)
|
|
|
|
|
{
|
|
|
|
|
writer.WriteValue((string)value);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-01 12:17:38 +00:00
|
|
|
|
public override AbsolutePath ReadJson(JsonReader reader, Type objectType, AbsolutePath existingValue,
|
|
|
|
|
bool hasExistingValue,
|
2020-03-26 12:28:03 +00:00
|
|
|
|
JsonSerializer serializer)
|
|
|
|
|
{
|
2020-04-03 23:23:13 +00:00
|
|
|
|
return (AbsolutePath)(string)reader.Value!;
|
2020-03-26 12:28:03 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-04-01 12:17:38 +00:00
|
|
|
|
|
2020-04-01 19:15:23 +00:00
|
|
|
|
private class PercentConverter : JsonConverter<Percent>
|
|
|
|
|
{
|
|
|
|
|
public override Percent ReadJson(JsonReader reader, Type objectType, Percent existingValue, bool hasExistingValue, JsonSerializer serializer)
|
|
|
|
|
{
|
2020-04-03 23:23:13 +00:00
|
|
|
|
double d = (double)reader.Value!;
|
2020-04-01 19:15:23 +00:00
|
|
|
|
return Percent.FactoryPutInRange(d);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void WriteJson(JsonWriter writer, Percent value, JsonSerializer serializer)
|
|
|
|
|
{
|
|
|
|
|
writer.WriteValue(value.Value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-26 12:28:03 +00:00
|
|
|
|
private class HashRelativePathConverter : JsonConverter<HashRelativePath>
|
|
|
|
|
{
|
|
|
|
|
public override void WriteJson(JsonWriter writer, HashRelativePath value, JsonSerializer serializer)
|
|
|
|
|
{
|
|
|
|
|
writer.WriteStartArray();
|
|
|
|
|
writer.WriteValue(value.BaseHash.ToBase64());
|
|
|
|
|
foreach (var itm in value.Paths)
|
|
|
|
|
writer.WriteValue((string)itm);
|
|
|
|
|
writer.WriteEndArray();
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-01 12:17:38 +00:00
|
|
|
|
public override HashRelativePath ReadJson(JsonReader reader, Type objectType,
|
|
|
|
|
HashRelativePath existingValue, bool hasExistingValue,
|
2020-03-26 12:28:03 +00:00
|
|
|
|
JsonSerializer serializer)
|
|
|
|
|
{
|
|
|
|
|
if (reader.TokenType != JsonToken.StartArray)
|
|
|
|
|
throw new JsonException("Invalid JSON state while reading Hash Relative Path");
|
|
|
|
|
reader.Read();
|
|
|
|
|
|
2020-04-03 23:23:13 +00:00
|
|
|
|
var hash = Hash.FromBase64((string)reader.Value!);
|
2020-03-26 12:28:03 +00:00
|
|
|
|
var paths = new List<RelativePath>();
|
|
|
|
|
|
|
|
|
|
reader.Read();
|
|
|
|
|
while (reader.TokenType != JsonToken.EndArray)
|
|
|
|
|
{
|
2020-04-03 23:23:13 +00:00
|
|
|
|
paths.Add((RelativePath)(string)reader.Value!);
|
2020-03-26 12:28:03 +00:00
|
|
|
|
reader.Read();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new HashRelativePath(hash, paths.ToArray());
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-04-01 12:17:38 +00:00
|
|
|
|
|
2020-03-26 12:28:03 +00:00
|
|
|
|
private class FullPathConverter : JsonConverter<FullPath>
|
|
|
|
|
{
|
|
|
|
|
public override void WriteJson(JsonWriter writer, FullPath value, JsonSerializer serializer)
|
|
|
|
|
{
|
|
|
|
|
writer.WriteStartArray();
|
|
|
|
|
writer.WriteValue((string)value.Base);
|
|
|
|
|
foreach (var itm in value.Paths)
|
|
|
|
|
writer.WriteValue((string)itm);
|
|
|
|
|
writer.WriteEndArray();
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-01 12:17:38 +00:00
|
|
|
|
public override FullPath ReadJson(JsonReader reader, Type objectType, FullPath existingValue,
|
|
|
|
|
bool hasExistingValue,
|
2020-03-26 12:28:03 +00:00
|
|
|
|
JsonSerializer serializer)
|
|
|
|
|
{
|
|
|
|
|
if (reader.TokenType != JsonToken.StartArray)
|
|
|
|
|
throw new JsonException("Invalid JSON state while reading Hash Relative Path");
|
|
|
|
|
reader.Read();
|
|
|
|
|
|
2020-04-03 23:23:13 +00:00
|
|
|
|
var abs = (AbsolutePath)(string)reader.Value!;
|
2020-03-26 12:28:03 +00:00
|
|
|
|
var paths = new List<RelativePath>();
|
|
|
|
|
|
|
|
|
|
reader.Read();
|
|
|
|
|
while (reader.TokenType != JsonToken.EndArray)
|
|
|
|
|
{
|
2020-04-03 23:23:13 +00:00
|
|
|
|
paths.Add((RelativePath)(string)reader.Value!);
|
2020-03-26 12:28:03 +00:00
|
|
|
|
reader.Read();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new FullPath(abs, paths.ToArray());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-01 12:17:38 +00:00
|
|
|
|
public class GameConverter : JsonConverter<Game>
|
|
|
|
|
{
|
|
|
|
|
public override void WriteJson(JsonWriter writer, Game value, JsonSerializer serializer)
|
|
|
|
|
{
|
|
|
|
|
writer.WriteValue(Enum.GetName(typeof(Game), value));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override Game ReadJson(JsonReader reader, Type objectType, Game existingValue,
|
|
|
|
|
bool hasExistingValue,
|
|
|
|
|
JsonSerializer serializer)
|
|
|
|
|
{
|
2020-04-01 18:54:08 +00:00
|
|
|
|
// Backwards compatibility support
|
|
|
|
|
var str = reader.Value?.ToString();
|
|
|
|
|
if (string.IsNullOrWhiteSpace(str)) return default;
|
|
|
|
|
if (int.TryParse(str, out var i))
|
|
|
|
|
{
|
|
|
|
|
return (Game)i;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-12 19:47:28 +00:00
|
|
|
|
if (!GameRegistry.TryGetByFuzzyName(str, out var game))
|
2020-04-03 23:23:13 +00:00
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException($"Could not convert {str} to a Game type.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return game.Game;
|
2020-04-01 12:17:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-04-24 13:05:22 +00:00
|
|
|
|
|
|
|
|
|
public class IPathConverter : JsonConverter<IPath>
|
|
|
|
|
{
|
2020-06-26 17:33:38 +00:00
|
|
|
|
public override void WriteJson(JsonWriter writer, [AllowNull] IPath value, JsonSerializer serializer)
|
2020-04-24 13:05:22 +00:00
|
|
|
|
{
|
2020-12-31 23:39:18 +00:00
|
|
|
|
writer.WriteValue(value == null ? "" : value.ToString());
|
2020-04-24 13:05:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-26 17:33:38 +00:00
|
|
|
|
public override IPath ReadJson(JsonReader reader, Type objectType, [AllowNull] IPath existingValue, bool hasExistingValue, JsonSerializer serializer)
|
2020-04-24 13:05:22 +00:00
|
|
|
|
{
|
|
|
|
|
// Backwards compatibility support
|
|
|
|
|
var str = reader.Value?.ToString();
|
|
|
|
|
if (string.IsNullOrWhiteSpace(str)) return default(RelativePath);
|
|
|
|
|
|
|
|
|
|
if (Path.IsPathRooted(str))
|
|
|
|
|
return (AbsolutePath)str;
|
|
|
|
|
return (RelativePath)str;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-04-06 20:48:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-04-10 21:52:31 +00:00
|
|
|
|
public class JsonNameSerializationBinder : DefaultSerializationBinder
|
2020-04-06 20:48:54 +00:00
|
|
|
|
{
|
2020-04-20 21:36:33 +00:00
|
|
|
|
private static ConcurrentDictionary<string, Type> _nameToType = new ConcurrentDictionary<string, Type>();
|
|
|
|
|
private static ConcurrentDictionary<Type, string> _typeToName = new ConcurrentDictionary<Type, string>();
|
2020-04-12 16:06:37 +00:00
|
|
|
|
private static bool _init;
|
2020-04-06 20:48:54 +00:00
|
|
|
|
|
|
|
|
|
public JsonNameSerializationBinder()
|
|
|
|
|
{
|
2020-04-12 16:06:37 +00:00
|
|
|
|
if (_init)
|
2020-04-06 22:02:01 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2020-04-06 20:48:54 +00:00
|
|
|
|
var customDisplayNameTypes =
|
|
|
|
|
AppDomain.CurrentDomain
|
|
|
|
|
.GetAssemblies()
|
2020-04-06 22:02:01 +00:00
|
|
|
|
.Where(a => a.FullName != null && !a.FullName.StartsWith("System") && !a.FullName.StartsWith("Microsoft"))
|
2020-04-06 20:48:54 +00:00
|
|
|
|
.SelectMany(a =>
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
return a.GetTypes();
|
|
|
|
|
}
|
|
|
|
|
catch (ReflectionTypeLoadException)
|
|
|
|
|
{
|
|
|
|
|
return new Type[0];
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
//concat with references if desired
|
|
|
|
|
.Where(x => x
|
|
|
|
|
.GetCustomAttributes(false)
|
|
|
|
|
.Any(y => y is JsonNameAttribute));
|
|
|
|
|
|
2020-04-20 21:36:33 +00:00
|
|
|
|
foreach (var type in customDisplayNameTypes)
|
|
|
|
|
{
|
|
|
|
|
var strName = type.GetCustomAttributes(false).OfType<JsonNameAttribute>().First().Name;
|
|
|
|
|
_typeToName.TryAdd(type, strName);
|
|
|
|
|
_nameToType.TryAdd(strName, type);
|
|
|
|
|
}
|
2020-04-12 16:06:37 +00:00
|
|
|
|
_init = true;
|
2020-04-06 20:48:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-10 21:52:31 +00:00
|
|
|
|
public override Type BindToType(string? assemblyName, string typeName)
|
2020-04-06 20:48:54 +00:00
|
|
|
|
{
|
|
|
|
|
if (typeName.EndsWith("[]"))
|
|
|
|
|
{
|
|
|
|
|
var result = BindToType(assemblyName, typeName.Substring(0, typeName.Length - 2));
|
|
|
|
|
return result.MakeArrayType();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_nameToType.ContainsKey(typeName))
|
|
|
|
|
return _nameToType[typeName];
|
|
|
|
|
|
2020-04-20 21:36:33 +00:00
|
|
|
|
if (assemblyName != null)
|
|
|
|
|
{
|
|
|
|
|
var assembly = Assembly.Load(assemblyName);
|
|
|
|
|
var tp = assembly
|
|
|
|
|
.GetTypes()
|
|
|
|
|
.FirstOrDefault(tp => Enumerable.OfType<JsonNameAttribute>(tp.GetCustomAttributes(false))
|
|
|
|
|
.Any(a => a.Name == typeName));
|
|
|
|
|
|
|
|
|
|
if (tp != null)
|
|
|
|
|
{
|
|
|
|
|
_typeToName.TryAdd(tp, typeName);
|
|
|
|
|
_nameToType.TryAdd(typeName, tp);
|
|
|
|
|
return tp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-06 20:48:54 +00:00
|
|
|
|
var val = Type.GetType(typeName);
|
|
|
|
|
if (val != null)
|
|
|
|
|
return val;
|
|
|
|
|
|
2020-04-10 21:52:31 +00:00
|
|
|
|
return base.BindToType(assemblyName, typeName);
|
2020-04-06 20:48:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-10 21:52:31 +00:00
|
|
|
|
public override void BindToName(Type serializedType, out string? assemblyName, out string? typeName)
|
2020-04-06 20:48:54 +00:00
|
|
|
|
{
|
2020-04-10 21:52:31 +00:00
|
|
|
|
if (serializedType.FullName?.StartsWith("System.") ?? false)
|
|
|
|
|
{
|
|
|
|
|
base.BindToName(serializedType, out assemblyName, out typeName);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-06 20:48:54 +00:00
|
|
|
|
if (!_typeToName.ContainsKey(serializedType))
|
|
|
|
|
{
|
2020-04-15 11:53:49 +00:00
|
|
|
|
var custom = serializedType.GetCustomAttributes(false)
|
|
|
|
|
.OfType<JsonNameAttribute>().FirstOrDefault();
|
|
|
|
|
if (custom == null)
|
|
|
|
|
{
|
|
|
|
|
throw new InvalidDataException($"No Binding name for {serializedType}");
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-20 21:36:33 +00:00
|
|
|
|
_nameToType.TryAdd(custom.Name, serializedType);
|
|
|
|
|
_typeToName.TryAdd(serializedType, custom.Name);
|
|
|
|
|
assemblyName = serializedType.Assembly.FullName;
|
2020-04-15 11:53:49 +00:00
|
|
|
|
typeName = custom.Name;
|
|
|
|
|
return;
|
2020-04-06 20:48:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var name = _typeToName[serializedType];
|
|
|
|
|
|
2020-04-20 21:36:33 +00:00
|
|
|
|
assemblyName = serializedType.Assembly.FullName;
|
2020-04-06 20:48:54 +00:00
|
|
|
|
typeName = name;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-03-26 12:28:03 +00:00
|
|
|
|
}
|
|
|
|
|
}
|