Skip to content

Commit

Permalink
refactor: [TypeWrapping]型の読み替え処理をTypeConverterとして1クラスに分離
Browse files Browse the repository at this point in the history
今後の機能拡充に際して、同様の処理が様々な箇所で必要となるため
  • Loading branch information
automatic9045 committed Dec 21, 2023
1 parent ce85a40 commit 88a5692
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

using UnembeddedResources;

namespace TypeWrapping
{
public partial class WrapTypeSet
Expand All @@ -17,27 +14,6 @@ private partial class MemberLoader
{
private class WrappedTypeResolver : TypeLoaderBase
{
private class ResourceSet
{
private readonly ResourceLocalizer Localizer = ResourceLocalizer.FromResXOfType<WrappedTypeResolver>(@"TypeWrapping\WrapTypeSet");

[ResourceStringHolder(nameof(Localizer))] public Resource<string> ElementTypesButArrayNotSupported { get; private set; }

public ResourceSet()
{
ResourceLoader.LoadAndSetAll(this);
}
}

private static readonly Lazy<ResourceSet> Resources = new Lazy<ResourceSet>();

static WrappedTypeResolver()
{
#if DEBUG
_ = Resources.Value;
#endif
}

private readonly Dictionary<Type, Type> WrapperToOriginal = new Dictionary<Type, Type>();
private readonly Dictionary<Type, Type> BridgedWrapperToWrapper = new Dictionary<Type, Type>();
private readonly ConcurrentDictionary<Type, List<Type>> WrapperToBridgedWrapper = new ConcurrentDictionary<Type, List<Type>>();
Expand Down Expand Up @@ -98,57 +74,8 @@ private void Load(IEnumerable<XElement> elements, IEnumerable<XElement> parentCl

public Type GetOriginal(Type wrapper)
{
if (wrapper.IsGenericParameter)
{
Type declaringWrapper = wrapper.DeclaringType;
Type declaringOriginal = GetOriginal(declaringWrapper);

return (declaringOriginal as TypeInfo).GenericTypeParameters[wrapper.GenericParameterPosition];
}
else if (wrapper.IsConstructedGenericType)
{
Type wrapperParent = wrapper.GetGenericTypeDefinition();
Type originalParent = ParseSimpleType(wrapperParent);

Type[] wrapperChildren = wrapper.GetGenericArguments();
Type[] originalChildren = new Type[wrapperChildren.Length];
for (int i = 0; i < wrapperChildren.Length; i++)
{
originalChildren[i] = ParseSimpleType(wrapperChildren[i]);
}

Type result = originalParent.MakeGenericType(originalChildren);
return result;
}
else if (wrapper.HasElementType)
{
if (!wrapper.IsArray || wrapper.Name.Contains("*")) throw new NotSupportedException(Resources.Value.ElementTypesButArrayNotSupported.Value);

Type wrapperElement = wrapper.GetElementType();
Type originalElement = ParseSimpleType(wrapperElement);

int rank = wrapper.GetArrayRank();
Type result = rank == 1 ? originalElement.MakeArrayType() : originalElement.MakeArrayType(rank);
return result;
}
else
{
return ParseSimpleType(wrapper);
}


Type ParseSimpleType(Type simpleWrapper, bool allowBridgedtypes = true)
{
if (!WrapperToOriginal.TryGetValue(simpleWrapper, out Type result))
{
if (allowBridgedtypes && BridgedWrapperToWrapper.TryGetValue(simpleWrapper, out Type bridgedTo))
{
return ParseSimpleType(bridgedTo, false);
}
}

return result ?? simpleWrapper;
}
TypeConverter converter = new TypeConverter(WrapperToOriginal, BridgedWrapperToWrapper);
return converter.Convert(wrapper);
}

public (Type Wrapper, Type Original) Resolve(string wrapperName)
Expand Down
99 changes: 99 additions & 0 deletions Libs/TypeWrapping/TypeConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

using UnembeddedResources;

namespace TypeWrapping
{
public class TypeConverter
{
private class ResourceSet
{
private readonly ResourceLocalizer Localizer = ResourceLocalizer.FromResXOfType<TypeConverter>("TypeWrapping");

[ResourceStringHolder(nameof(Localizer))] public Resource<string> ElementTypesButArrayNotSupported { get; private set; }

public ResourceSet()
{
ResourceLoader.LoadAndSetAll(this);
}
}

private static readonly Lazy<ResourceSet> Resources = new Lazy<ResourceSet>();

static TypeConverter()
{
#if DEBUG
_ = Resources.Value;
#endif
}

private readonly Dictionary<Type, Type> ConvertibleTypes;
private readonly Dictionary<Type, Type> TypeBridges;

public TypeConverter(Dictionary<Type, Type> convertibleTypes, Dictionary<Type, Type> typeBridges = null)
{
ConvertibleTypes = convertibleTypes;
TypeBridges = typeBridges ?? new Dictionary<Type, Type>();
}

public Type Convert(Type source)
{
if (source.IsGenericParameter)
{
Type declaringSource = source.DeclaringType;
Type declaringOriginal = Convert(declaringSource);

return (declaringOriginal as TypeInfo).GenericTypeParameters[source.GenericParameterPosition];
}
else if (source.IsConstructedGenericType)
{
Type sourceParent = source.GetGenericTypeDefinition();
Type originalParent = ParseSimpleType(sourceParent);

Type[] sourceChildren = source.GetGenericArguments();
Type[] originalChildren = new Type[sourceChildren.Length];
for (int i = 0; i < sourceChildren.Length; i++)
{
originalChildren[i] = ParseSimpleType(sourceChildren[i]);
}

Type result = originalParent.MakeGenericType(originalChildren);
return result;
}
else if (source.HasElementType)
{
if (!source.IsArray || source.Name.Contains("*")) throw new NotSupportedException(Resources.Value.ElementTypesButArrayNotSupported.Value);

Type sourceElement = source.GetElementType();
Type originalElement = ParseSimpleType(sourceElement);

int rank = source.GetArrayRank();
Type result = rank == 1 ? originalElement.MakeArrayType() : originalElement.MakeArrayType(rank);
return result;
}
else
{
return ParseSimpleType(source);
}


Type ParseSimpleType(Type simpleSource, bool allowBridgedTypes = true)
{
if (!ConvertibleTypes.TryGetValue(simpleSource, out Type result))
{
if (allowBridgedTypes && TypeBridges.TryGetValue(simpleSource, out Type bridgedTo))
{
return ParseSimpleType(bridgedTo, false);
}
}

return result ?? simpleSource;
}
}
}
}
5 changes: 3 additions & 2 deletions Libs/TypeWrapping/TypeWrapping.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
<Compile Include="Loader\WrapTypeSet.TypeLoaderBase.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SchemaProvider.cs" />
<Compile Include="TypeConverter.cs" />
<Compile Include="TypeMemberSet\ClassMemberSet.cs" />
<Compile Include="TypeMemberSet\DelegateMemberSet.cs" />
<Compile Include="TypeMemberSet\EnumMemberSet.cs" />
Expand All @@ -68,8 +69,8 @@
<Content Include="Resources\WrapTypeSet\ElementParser.resx" />
<Content Include="Resources\WrapTypeSet\MemberLoader.ja.resx" />
<Content Include="Resources\WrapTypeSet\MemberLoader.resx" />
<Content Include="Resources\WrapTypeSet\WrappedTypeResolver.ja.resx" />
<Content Include="Resources\WrapTypeSet\WrappedTypeResolver.resx" />
<Content Include="Resources\TypeConverter.ja.resx" />
<Content Include="Resources\TypeConverter.resx" />
<Content Include="Resources\WrapTypeSet\WrapTypeSet.ja.resx" />
<Content Include="Resources\WrapTypeSet\WrapTypeSet.resx" />
<EmbeddedResource Include="WrapTypesXmlSchema.xsd">
Expand Down

0 comments on commit 88a5692

Please sign in to comment.