|
@ -1,6 +1,6 @@ |
|
|
using IPA.Config.Data; |
|
|
using IPA.Config.Data; |
|
|
using IPA.Config.Stores.Attributes; |
|
|
using IPA.Config.Stores.Attributes; |
|
|
using IPA.Logging; |
|
|
|
|
|
|
|
|
using IPA.Logging; |
|
|
using System; |
|
|
using System; |
|
|
using System.Collections.Generic; |
|
|
using System.Collections.Generic; |
|
|
using System.Linq; |
|
|
using System.Linq; |
|
@ -90,28 +90,28 @@ namespace IPA.Config.Stores.Converters |
|
|
|
|
|
|
|
|
private static ValueConverter<T> MakeDefault() |
|
|
private static ValueConverter<T> MakeDefault() |
|
|
{ |
|
|
{ |
|
|
var t = typeof(T); |
|
|
|
|
|
|
|
|
var t = typeof(T); |
|
|
//Logger.log.Debug($"Converter<{t}>.MakeDefault()");
|
|
|
//Logger.log.Debug($"Converter<{t}>.MakeDefault()");
|
|
|
|
|
|
|
|
|
if (t.IsValueType) |
|
|
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
|
|
|
{ // 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<>)) |
|
|
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)) |
|
|
{ // this is a Nullable
|
|
|
|
|
|
|
|
|
{ // this is a Nullable
|
|
|
//Logger.log.Debug($"gives NullableConverter<{Nullable.GetUnderlyingType(t)}>");
|
|
|
//Logger.log.Debug($"gives NullableConverter<{Nullable.GetUnderlyingType(t)}>");
|
|
|
return Activator.CreateInstance(typeof(NullableConverter<>).MakeGenericType(Nullable.GetUnderlyingType(t))) as ValueConverter<T>; |
|
|
return Activator.CreateInstance(typeof(NullableConverter<>).MakeGenericType(Nullable.GetUnderlyingType(t))) as ValueConverter<T>; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
//Logger.log.Debug($"gives converter for value type {t}");
|
|
|
//Logger.log.Debug($"gives converter for value type {t}");
|
|
|
var valConv = Activator.CreateInstance(typeof(Converter.ValConv<>).MakeGenericType(t)) as Converter.IValConv<T>; |
|
|
var valConv = Activator.CreateInstance(typeof(Converter.ValConv<>).MakeGenericType(t)) as Converter.IValConv<T>; |
|
|
return valConv.Get(); |
|
|
return valConv.Get(); |
|
|
} |
|
|
} |
|
|
else if (t == typeof(string)) |
|
|
else if (t == typeof(string)) |
|
|
{ |
|
|
|
|
|
|
|
|
{ |
|
|
//Logger.log.Debug($"gives StringConverter");
|
|
|
//Logger.log.Debug($"gives StringConverter");
|
|
|
return new StringConverter() as ValueConverter<T>; |
|
|
return new StringConverter() as ValueConverter<T>; |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
|
|
|
|
|
|
{ |
|
|
//Logger.log.Debug($"gives CustomObjectConverter<{t}>");
|
|
|
//Logger.log.Debug($"gives CustomObjectConverter<{t}>");
|
|
|
return Activator.CreateInstance(typeof(CustomObjectConverter<>).MakeGenericType(t)) as ValueConverter<T>; |
|
|
return Activator.CreateInstance(typeof(CustomObjectConverter<>).MakeGenericType(t)) as ValueConverter<T>; |
|
|
} |
|
|
} |
|
@ -264,6 +264,184 @@ namespace IPA.Config.Stores.Converters |
|
|
=> Value.Integer(Convert.ToInt64(obj)); |
|
|
=> Value.Integer(Convert.ToInt64(obj)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// A converter for instances of <see cref="IDictionary{TKey, TValue}"/>.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <typeparam name="TValue">the value type of the dictionary</typeparam>
|
|
|
|
|
|
public class IDictionaryConverter<TValue> : ValueConverter<IDictionary<string, TValue>> |
|
|
|
|
|
{ |
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Gets the converter for the dictionary's value type.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
protected ValueConverter<TValue> BaseConverter { get; } |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructs an <see cref="IDictionaryConverter{TValue}"/> using the default converter for the value type.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public IDictionaryConverter() : this(Converter<TValue>.Default) { } |
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructs an <see cref="IDictionaryConverter{TValue}"/> using the specified converter for the value.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="converter">the converter for the value</param>
|
|
|
|
|
|
public IDictionaryConverter(ValueConverter<TValue> converter) |
|
|
|
|
|
=> BaseConverter = converter; |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Converts a <see cref="Map"/> to an <see cref="IDictionary{TKey, TValue}"/> that is represented by it.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="value">the <see cref="Map"/> to convert</param>
|
|
|
|
|
|
/// <param name="parent">the parent that will own the resulting object</param>
|
|
|
|
|
|
/// <returns>the deserialized dictionary</returns>
|
|
|
|
|
|
public override IDictionary<string, TValue> 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)); |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Serializes an <see cref="IDictionary{TKey, TValue}"/> into a <see cref="Map"/> containing its values.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="obj">the dictionary to serialize</param>
|
|
|
|
|
|
/// <param name="parent">the object that owns the dictionary</param>
|
|
|
|
|
|
/// <returns>the dictionary serialized as a <see cref="Map"/></returns>
|
|
|
|
|
|
public override Value ToValue(IDictionary<string, TValue> obj, object parent) |
|
|
|
|
|
=> Value.From(obj.Select(p => new KeyValuePair<string, Value>(p.Key, BaseConverter.ToValue(p.Value, parent)))); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// A converter for instances of <see cref="IDictionary{TKey, TValue}"/>, specifying a value converter as a type parameter.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <typeparam name="TValue">the value type of the dictionary</typeparam>
|
|
|
|
|
|
/// <typeparam name="TConverter">the converter type for values</typeparam>
|
|
|
|
|
|
public sealed class IDictionaryConverter<TValue, TConverter> : IDictionaryConverter<TValue> |
|
|
|
|
|
where TConverter : ValueConverter<TValue>, new() |
|
|
|
|
|
{ |
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructs a new <see cref="IDictionaryConverter{TValue, TConverter}"/> with a new instance of
|
|
|
|
|
|
/// <typeparamref name="TConverter"/> as the value converter.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public IDictionaryConverter() : base(new TConverter()) { } |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// A converter for instances of <see cref="Dictionary{TKey, TValue}"/>.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <typeparam name="TValue">the value type of the dictionary</typeparam>
|
|
|
|
|
|
public class DictionaryConverter<TValue> : ValueConverter<Dictionary<string, TValue>> |
|
|
|
|
|
{ |
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Gets the converter for the dictionary's value type.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
protected ValueConverter<TValue> BaseConverter { get; } |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructs an <see cref="IDictionaryConverter{TValue}"/> using the default converter for the value type.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public DictionaryConverter() : this(Converter<TValue>.Default) { } |
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructs an <see cref="IDictionaryConverter{TValue}"/> using the specified converter for the value.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="converter">the converter for the value</param>
|
|
|
|
|
|
public DictionaryConverter(ValueConverter<TValue> converter) |
|
|
|
|
|
=> BaseConverter = converter; |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Converts a <see cref="Map"/> to a <see cref="Dictionary{TKey, TValue}"/> that is represented by it.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="value">the <see cref="Map"/> to convert</param>
|
|
|
|
|
|
/// <param name="parent">the parent that will own the resulting object</param>
|
|
|
|
|
|
/// <returns>the deserialized dictionary</returns>
|
|
|
|
|
|
public override Dictionary<string, TValue> 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)); |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Serializes a <see cref="Dictionary{TKey, TValue}"/> into a <see cref="Map"/> containing its values.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="obj">the dictionary to serialize</param>
|
|
|
|
|
|
/// <param name="parent">the object that owns the dictionary</param>
|
|
|
|
|
|
/// <returns>the dictionary serialized as a <see cref="Map"/></returns>
|
|
|
|
|
|
public override Value ToValue(Dictionary<string, TValue> obj, object parent) |
|
|
|
|
|
=> Value.From(obj.Select(p => new KeyValuePair<string, Value>(p.Key, BaseConverter.ToValue(p.Value, parent)))); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// A converter for instances of <see cref="Dictionary{TKey, TValue}"/>, specifying a value converter as a type parameter.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <typeparam name="TValue">the value type of the dictionary</typeparam>
|
|
|
|
|
|
/// <typeparam name="TConverter">the converter type for values</typeparam>
|
|
|
|
|
|
public sealed class DictionaryConverter<TValue, TConverter> : DictionaryConverter<TValue> |
|
|
|
|
|
where TConverter : ValueConverter<TValue>, new() |
|
|
|
|
|
{ |
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructs a new <see cref="IDictionaryConverter{TValue, TConverter}"/> with a new instance of
|
|
|
|
|
|
/// <typeparamref name="TConverter"/> as the value converter.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public DictionaryConverter() : base(new TConverter()) { } |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#if NET4
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// A converter for instances of <see cref="IReadOnlyDictionary{TKey, TValue}"/>.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <typeparam name="TValue">the value type of the dictionary</typeparam>
|
|
|
|
|
|
public class IReadOnlyDictionaryConverter<TValue> : ValueConverter<IReadOnlyDictionary<string, TValue>> |
|
|
|
|
|
{ |
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Gets the converter for the dictionary's value type.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
protected ValueConverter<TValue> BaseConverter { get; } |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructs an <see cref="IReadOnlyDictionaryConverter{TValue}"/> using the default converter for the value type.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public IReadOnlyDictionaryConverter() : this(Converter<TValue>.Default) { } |
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructs an <see cref="IReadOnlyDictionaryConverter{TValue}"/> using the specified converter for the value.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="converter">the converter for the value</param>
|
|
|
|
|
|
public IReadOnlyDictionaryConverter(ValueConverter<TValue> converter) |
|
|
|
|
|
=> BaseConverter = converter; |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Converts a <see cref="Map"/> to an <see cref="IDictionary{TKey, TValue}"/> that is represented by it.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="value">the <see cref="Map"/> to convert</param>
|
|
|
|
|
|
/// <param name="parent">the parent that will own the resulting object</param>
|
|
|
|
|
|
/// <returns>the deserialized dictionary</returns>
|
|
|
|
|
|
public override IReadOnlyDictionary<string, TValue> 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)); |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Serializes an <see cref="IDictionary{TKey, TValue}"/> into a <see cref="Map"/> containing its values.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="obj">the dictionary to serialize</param>
|
|
|
|
|
|
/// <param name="parent">the object that owns the dictionary</param>
|
|
|
|
|
|
/// <returns>the dictionary serialized as a <see cref="Map"/></returns>
|
|
|
|
|
|
public override Value ToValue(IReadOnlyDictionary<string, TValue> obj, object parent) |
|
|
|
|
|
=> Value.From(obj.Select(p => new KeyValuePair<string, Value>(p.Key, BaseConverter.ToValue(p.Value, parent)))); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// A converter for instances of <see cref="IReadOnlyDictionary{TKey, TValue}"/>, specifying a value converter as a type parameter.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <typeparam name="TValue">the value type of the dictionary</typeparam>
|
|
|
|
|
|
/// <typeparam name="TConverter">the converter type for values</typeparam>
|
|
|
|
|
|
public sealed class IReadOnlyDictionaryConverter<TValue, TConverter> : IReadOnlyDictionaryConverter<TValue> |
|
|
|
|
|
where TConverter : ValueConverter<TValue>, new() |
|
|
|
|
|
{ |
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructs a new <see cref="IReadOnlyDictionaryConverter{TValue, TConverter}"/> with a new instance of
|
|
|
|
|
|
/// <typeparamref name="TConverter"/> as the value converter.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public IReadOnlyDictionaryConverter() : base(new TConverter()) { } |
|
|
|
|
|
} |
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
internal class StringConverter : ValueConverter<string> |
|
|
internal class StringConverter : ValueConverter<string> |
|
|
{ |
|
|
{ |
|
|
public override string FromValue(Value value, object parent) |
|
|
public override string FromValue(Value value, object parent) |
|
|