From a85a99005b336435f54af915870a9d4e84447b7c Mon Sep 17 00:00:00 2001 From: Anairkoen Schno Date: Wed, 1 Apr 2020 21:56:03 -0500 Subject: [PATCH] Added converter types for the various dictionary types --- .../Config/Stores/CollectionConverter.cs | 6 +- IPA.Loader/Config/Stores/Converters.cs | 192 +++++++++++++++++- 2 files changed, 188 insertions(+), 10 deletions(-) diff --git a/IPA.Loader/Config/Stores/CollectionConverter.cs b/IPA.Loader/Config/Stores/CollectionConverter.cs index 55cfe034..635ba49c 100644 --- a/IPA.Loader/Config/Stores/CollectionConverter.cs +++ b/IPA.Loader/Config/Stores/CollectionConverter.cs @@ -4,8 +4,8 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using IPA.Config.Data; -using IPA.Logging; - +using IPA.Logging; + namespace IPA.Config.Stores.Converters { /// @@ -81,7 +81,7 @@ namespace IPA.Config.Stores.Converters /// the object owning /// the that was serialized into /// - public override Value ToValue(TCollection obj, object parent) + public override Value ToValue(TCollection obj, object parent) => Value.From(obj.Select(t => BaseConverter.ToValue(t, parent))); } /// diff --git a/IPA.Loader/Config/Stores/Converters.cs b/IPA.Loader/Config/Stores/Converters.cs index 1a7367a4..42740e17 100644 --- a/IPA.Loader/Config/Stores/Converters.cs +++ b/IPA.Loader/Config/Stores/Converters.cs @@ -1,6 +1,6 @@ using IPA.Config.Data; using IPA.Config.Stores.Attributes; -using IPA.Logging; +using IPA.Logging; using System; using System.Collections.Generic; using System.Linq; @@ -90,28 +90,28 @@ namespace IPA.Config.Stores.Converters private static ValueConverter MakeDefault() { - var t = typeof(T); + var t = typeof(T); //Logger.log.Debug($"Converter<{t}>.MakeDefault()"); if (t.IsValueType) { // we have to do this garbo to make it accept the thing that we know is a value type at instantiation time if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)) - { // this is a Nullable + { // this is a Nullable //Logger.log.Debug($"gives NullableConverter<{Nullable.GetUnderlyingType(t)}>"); return Activator.CreateInstance(typeof(NullableConverter<>).MakeGenericType(Nullable.GetUnderlyingType(t))) as ValueConverter; - } - + } + //Logger.log.Debug($"gives converter for value type {t}"); var valConv = Activator.CreateInstance(typeof(Converter.ValConv<>).MakeGenericType(t)) as Converter.IValConv; return valConv.Get(); } else if (t == typeof(string)) - { + { //Logger.log.Debug($"gives StringConverter"); return new StringConverter() as ValueConverter; } else - { + { //Logger.log.Debug($"gives CustomObjectConverter<{t}>"); return Activator.CreateInstance(typeof(CustomObjectConverter<>).MakeGenericType(t)) as ValueConverter; } @@ -264,6 +264,184 @@ namespace IPA.Config.Stores.Converters => Value.Integer(Convert.ToInt64(obj)); } + /// + /// A converter for instances of . + /// + /// the value type of the dictionary + public class IDictionaryConverter : ValueConverter> + { + /// + /// Gets the converter for the dictionary's value type. + /// + protected ValueConverter BaseConverter { get; } + + /// + /// Constructs an using the default converter for the value type. + /// + public IDictionaryConverter() : this(Converter.Default) { } + /// + /// Constructs an using the specified converter for the value. + /// + /// the converter for the value + public IDictionaryConverter(ValueConverter converter) + => BaseConverter = converter; + + /// + /// Converts a to an that is represented by it. + /// + /// the to convert + /// the parent that will own the resulting object + /// the deserialized dictionary + public override IDictionary FromValue(Value value, object parent) + => (value as Map)?.Select(kvp => (kvp.Key, val: BaseConverter.FromValue(kvp.Value, parent))) + ?.ToDictionary(p => p.Key, p => p.val) + ?? throw new ArgumentException("Value not a map", nameof(value)); + + /// + /// Serializes an into a containing its values. + /// + /// the dictionary to serialize + /// the object that owns the dictionary + /// the dictionary serialized as a + public override Value ToValue(IDictionary obj, object parent) + => Value.From(obj.Select(p => new KeyValuePair(p.Key, BaseConverter.ToValue(p.Value, parent)))); + } + + /// + /// A converter for instances of , specifying a value converter as a type parameter. + /// + /// the value type of the dictionary + /// the converter type for values + public sealed class IDictionaryConverter : IDictionaryConverter + where TConverter : ValueConverter, new() + { + /// + /// Constructs a new with a new instance of + /// as the value converter. + /// + public IDictionaryConverter() : base(new TConverter()) { } + } + + + /// + /// A converter for instances of . + /// + /// the value type of the dictionary + public class DictionaryConverter : ValueConverter> + { + /// + /// Gets the converter for the dictionary's value type. + /// + protected ValueConverter BaseConverter { get; } + + /// + /// Constructs an using the default converter for the value type. + /// + public DictionaryConverter() : this(Converter.Default) { } + /// + /// Constructs an using the specified converter for the value. + /// + /// the converter for the value + public DictionaryConverter(ValueConverter converter) + => BaseConverter = converter; + + /// + /// Converts a to a that is represented by it. + /// + /// the to convert + /// the parent that will own the resulting object + /// the deserialized dictionary + public override Dictionary FromValue(Value value, object parent) + => (value as Map)?.Select(kvp => (kvp.Key, val: BaseConverter.FromValue(kvp.Value, parent))) + ?.ToDictionary(p => p.Key, p => p.val) + ?? throw new ArgumentException("Value not a map", nameof(value)); + + /// + /// Serializes a into a containing its values. + /// + /// the dictionary to serialize + /// the object that owns the dictionary + /// the dictionary serialized as a + public override Value ToValue(Dictionary obj, object parent) + => Value.From(obj.Select(p => new KeyValuePair(p.Key, BaseConverter.ToValue(p.Value, parent)))); + } + + /// + /// A converter for instances of , specifying a value converter as a type parameter. + /// + /// the value type of the dictionary + /// the converter type for values + public sealed class DictionaryConverter : DictionaryConverter + where TConverter : ValueConverter, new() + { + /// + /// Constructs a new with a new instance of + /// as the value converter. + /// + public DictionaryConverter() : base(new TConverter()) { } + } + +#if NET4 + + /// + /// A converter for instances of . + /// + /// the value type of the dictionary + public class IReadOnlyDictionaryConverter : ValueConverter> + { + /// + /// Gets the converter for the dictionary's value type. + /// + protected ValueConverter BaseConverter { get; } + + /// + /// Constructs an using the default converter for the value type. + /// + public IReadOnlyDictionaryConverter() : this(Converter.Default) { } + /// + /// Constructs an using the specified converter for the value. + /// + /// the converter for the value + public IReadOnlyDictionaryConverter(ValueConverter converter) + => BaseConverter = converter; + + /// + /// Converts a to an that is represented by it. + /// + /// the to convert + /// the parent that will own the resulting object + /// the deserialized dictionary + public override IReadOnlyDictionary FromValue(Value value, object parent) + => (value as Map)?.Select(kvp => (kvp.Key, val: BaseConverter.FromValue(kvp.Value, parent))) + ?.ToDictionary(p => p.Key, p => p.val) + ?? throw new ArgumentException("Value not a map", nameof(value)); + + /// + /// Serializes an into a containing its values. + /// + /// the dictionary to serialize + /// the object that owns the dictionary + /// the dictionary serialized as a + public override Value ToValue(IReadOnlyDictionary obj, object parent) + => Value.From(obj.Select(p => new KeyValuePair(p.Key, BaseConverter.ToValue(p.Value, parent)))); + } + + /// + /// A converter for instances of , specifying a value converter as a type parameter. + /// + /// the value type of the dictionary + /// the converter type for values + public sealed class IReadOnlyDictionaryConverter : IReadOnlyDictionaryConverter + where TConverter : ValueConverter, new() + { + /// + /// Constructs a new with a new instance of + /// as the value converter. + /// + public IReadOnlyDictionaryConverter() : base(new TConverter()) { } + } +#endif + internal class StringConverter : ValueConverter { public override string FromValue(Value value, object parent)