diff --git a/IPA.Loader/Config/Stores/Converters.cs b/IPA.Loader/Config/Stores/Converters.cs index 42740e17..6c425288 100644 --- a/IPA.Loader/Config/Stores/Converters.cs +++ b/IPA.Loader/Config/Stores/Converters.cs @@ -88,33 +88,65 @@ namespace IPA.Config.Stores.Converters public static ValueConverter Default => defaultConverter ??= MakeDefault(); - private static ValueConverter MakeDefault() + internal static ValueConverter MakeDefault(bool allowValuesAndCustoms = true) { var t = typeof(T); //Logger.log.Debug($"Converter<{t}>.MakeDefault()"); + static ValueConverter MakeInstOf(Type ty) + => Activator.CreateInstance(ty) as ValueConverter; + + if (t.IsEnum) + { + return MakeInstOf(typeof(CaseInsensitiveEnumConverter<>).MakeGenericType(t)); + } + if (t == typeof(string)) + { + //Logger.log.Debug($"gives StringConverter"); + return new StringConverter() as ValueConverter; + } + if (t.IsGenericType) + { + var generic = t.GetGenericTypeDefinition(); + var args = t.GetGenericArguments(); + if (generic == typeof(List<>)) + return MakeInstOf(typeof(ListConverter<>).MakeGenericType(args)); + else if (generic == typeof(IList<>)) + return MakeInstOf(typeof(IListConverter<>).MakeGenericType(args)); + else if (generic == typeof(Dictionary<,>) && args[0] == typeof(string)) + return MakeInstOf(typeof(DictionaryConverter<>).MakeGenericType(args[1])); + else if (generic == typeof(IDictionary<,>) && args[0] == typeof(string)) + return MakeInstOf(typeof(IDictionaryConverter<>).MakeGenericType(args[1])); +#if NET4 + else if (generic == typeof(ISet<>)) + return MakeInstOf(typeof(ISetConverter<>).MakeGenericType(args)); + else if (generic == typeof(IReadOnlyDictionary<,>) && args[0] == typeof(string)) + return MakeInstOf(typeof(IReadOnlyDictionaryConverter<>).MakeGenericType(args[1])); +#endif + } + var iCollBase = t.GetInterfaces() + .FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollection<>)); + if (iCollBase != null && t.GetConstructor(Type.EmptyTypes) != null) + { // if it implements ICollection and has a default constructor + var valueType = iCollBase.GetGenericArguments().First(); + return MakeInstOf(typeof(CollectionConverter<,>).MakeGenericType(valueType, t)); + } + if (!allowValuesAndCustoms) return null; 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 //Logger.log.Debug($"gives NullableConverter<{Nullable.GetUnderlyingType(t)}>"); - return Activator.CreateInstance(typeof(NullableConverter<>).MakeGenericType(Nullable.GetUnderlyingType(t))) as ValueConverter; + return MakeInstOf(typeof(NullableConverter<>).MakeGenericType(Nullable.GetUnderlyingType(t))); } //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; - } + + //Logger.log.Debug($"gives CustomObjectConverter<{t}>"); + return MakeInstOf(typeof(CustomObjectConverter<>).MakeGenericType(t)); } }