Skip to content

Commit

Permalink
Improve IList and IDictionary types' conversion.
Browse files Browse the repository at this point in the history
  • Loading branch information
BearOffice committed Oct 9, 2022
1 parent f582940 commit ecf0b06
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 16 deletions.
2 changes: 1 addition & 1 deletion BearMarkupLanguage/BearMarkupLanguage.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Version>5.0.8</Version>
<Version>5.0.10</Version>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Authors>Bear</Authors>
<Company>Bear Office</Company>
Expand Down
21 changes: 16 additions & 5 deletions BearMarkupLanguage/Elements/DictionaryElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace BearMarkupLanguage.Elements;

internal class DictionaryElement: IBaseElement
internal class DictionaryElement : IBaseElement
{
internal OrderedDictionary<BasicElement, IBaseElement> ElementsDic { get; private init; }
public ParseMode PreferredParseMode
Expand Down Expand Up @@ -70,8 +70,19 @@ public object ConvertTo(Type targetType, IConversionProvider[] providers)
private object ConvertIDictionaryTo(Type targetType, IConversionProvider[] providers)
{
// IDictionary contains two generic arguments
var keyType = targetType.GetGenericArguments()[0];
var valueType = targetType.GetGenericArguments()[1];
var arguments = targetType.GetGenericArguments();
// try to find key and value types in target type if target type is not generic / doesn't contain 2 arguments
if (arguments.Length < 2)
{
var iDicInterface = targetType.GetInterfaces()
.FirstOrDefault(i => i.GetGenericTypeDefinitionIfHas() == typeof(IDictionary<,>));
arguments = iDicInterface?.GetGenericArguments();
}
if (arguments is null || arguments.Length < 2)
throw new TypeNotSupportException($"Cannot find key or value type in Type {targetType}");

var keyType = arguments[0];
var valueType = arguments[1];

var preferredKeyType = IBaseElement.PreferredElementType(keyType);
var preferredValueType = IBaseElement.PreferredElementType(valueType);
Expand Down Expand Up @@ -257,9 +268,9 @@ private string[] ExpandedParse()

private bool IsKeysNeedCollapse()
{
foreach((var key, _) in ElementsDic)
foreach ((var key, _) in ElementsDic)
{
if (key.Literal.IsNullOrWhiteSpace()
if (key.Literal.IsNullOrWhiteSpace()
|| key.Literal.StartsWith(' ') || key.Literal.EndsWith(' '))
return true;
}
Expand Down
28 changes: 21 additions & 7 deletions BearMarkupLanguage/Elements/ListElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace BearMarkupLanguage.Elements;

internal class ListElement: IBaseElement
internal class ListElement : IBaseElement
{
internal List<IBaseElement> ElementsList { get; private init; }
public ParseMode PreferredParseMode
Expand Down Expand Up @@ -50,11 +50,11 @@ internal ListElement(List<IBaseElement> elementsList)
ElementsList = elementsList;
}

public object ConvertTo(Type targetType, IConversionProvider[] providers)
public object ConvertTo(Type targetType, IConversionProvider[] providers)
{
if (targetType.IsListType())
{
if (!targetType.IsSZArray)
if (targetType.IsArray && !targetType.IsSZArray)
throw new TypeNotSupportException("Do not support multi-dimensional array.");

return ConvertIListTo(targetType, providers);
Expand All @@ -72,14 +72,28 @@ public object ConvertTo(Type targetType, IConversionProvider[] providers)

private object ConvertIListTo(Type targetType, IConversionProvider[] providers)
{
Type argumentType;
if (targetType.IsSZArray)
var argumentType = default(Type);

// Array needs a special treatment
if (targetType.IsArray && targetType.IsSZArray)
{
argumentType = targetType.GetElementType(); // Array needs a special treatment
argumentType = targetType.GetElementType();
}
else
{
argumentType = targetType.GetGenericArguments()[0]; // IList only contains one generic argument
// IList only contains one generic argument
var arguments = targetType.GetGenericArguments();
// try to find elements type in target type if target type is not generic / doesn't contain 1 argument
if (arguments.Length < 1)
{
var iListInterface = targetType.GetInterfaces()
.FirstOrDefault(i => i.GetGenericTypeDefinitionIfHas() == typeof(IList<>));
arguments = iListInterface?.GetGenericArguments();
}
if (arguments is null || arguments.Length < 1)
throw new TypeNotSupportException($"Cannot find elements type in Type {targetType}");

argumentType = arguments[0];
}

var preferredType = IBaseElement.PreferredElementType(argumentType);
Expand Down
4 changes: 2 additions & 2 deletions BearMarkupLanguage/Helpers/TypeExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,12 @@ internal static bool IsTupleType(this Type type)

internal static bool IsListType(this Type type)
{
return type.HasInterface(typeof(IList));
return type.HasInterface(typeof(IList)) || type.HasInterface(typeof(IList<>));
}

internal static bool IsDictionaryType(this Type type)
{
return type.HasInterface(typeof(IDictionary));
return type.HasInterface(typeof(IDictionary)) || type.HasInterface(typeof(IDictionary<,>));
}

internal static bool IsSerializableObject(this Type type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,6 @@ private static ElementResult ExpandedInterprete(string[] lines)
Message = "Key must be unique."
});


// key.Length + id's length
if (idIndex + 1 == lines[i].Length)
refLines[i] = "";
Expand Down

0 comments on commit ecf0b06

Please sign in to comment.