Skip to content

Commit

Permalink
feat: [TypeWrapping][BveTypes]型を互換性を維持しながら改名できるように
Browse files Browse the repository at this point in the history
旧名のものもObsolete指定の上維持することが可能に
  • Loading branch information
automatic9045 committed Dec 1, 2023
1 parent 68cbc0f commit 65597ed
Show file tree
Hide file tree
Showing 18 changed files with 173 additions and 50 deletions.
6 changes: 3 additions & 3 deletions Libs/BveTypes/BveTypeSet.InstanceCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public static BveTypeSet Load(Assembly bveAssembly, Version bveVersion, bool all

ProfileSelector profileSelector = new ProfileSelector(bveVersion);
Version profileVersion;
List<TypeMemberSetBase> types;
WrapTypeSet types;
using (Profile profile = profileSelector.GetProfileStream(allowLoadProfileForDifferentBveVersion))
{
profileVersion = profile.Version;
Expand All @@ -71,11 +71,11 @@ public static BveTypeSet Load(Assembly bveAssembly, Version bveVersion, bool all

using (Stream schema = SchemaProvider.GetSchemaStream())
{
types = WrapTypesXmlLoader.LoadFile(profile.Stream, schema, classWrapperTypes, bveTypes, additionalWrapTypes);
types = WrapTypeSet.LoadXml(profile.Stream, schema, classWrapperTypes, bveTypes, additionalWrapTypes);
}
}

BveTypeSet result = new BveTypeSet(types, profileVersion);
BveTypeSet result = new BveTypeSet(types.Types, types.Bridge, profileVersion);

ClassWrapperInitializer classWrapperInitializer = new ClassWrapperInitializer(result);
classWrapperInitializer.InitializeAll();
Expand Down
23 changes: 15 additions & 8 deletions Libs/BveTypes/BveTypeSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ static BveTypeSet()
}

private readonly Dictionary<Type, TypeMemberSetBase> Types;
private readonly TypeBridge Bridge;
private readonly Dictionary<Type, Type> OriginalAndWrapperTypes;
private readonly FastCache<Type, FastMethod> FromSourceMethodCache = new FastCache<Type, FastMethod>();

private BveTypeSet(IEnumerable<TypeMemberSetBase> types, Version profileVersion)
private BveTypeSet(IEnumerable<TypeMemberSetBase> types, TypeBridge bridge, Version profileVersion)
{
#if DEBUG
TypeMemberSetBase illegalType = types.FirstOrDefault(type =>
Expand All @@ -63,7 +64,12 @@ private BveTypeSet(IEnumerable<TypeMemberSetBase> types, Version profileVersion)
#endif

Types = types.ToDictionary(type => type.WrapperType, type => type);
OriginalAndWrapperTypes = types.ToDictionary(type => type.OriginalType, type => type.WrapperType);
Bridge = bridge;
OriginalAndWrapperTypes = types
.AsParallel()
.Select(type => (type.OriginalType, type.WrapperType))
.Concat(bridge.AsParallel().Select(x => (OriginalType: x.Key, x.Value.WrapperType)))
.ToDictionary(type => type.OriginalType, type => type.WrapperType);

ProfileVersion = profileVersion;
}
Expand All @@ -84,7 +90,7 @@ private BveTypeSet(IEnumerable<TypeMemberSetBase> types, Version profileVersion)
/// <seealso cref="GetClassInfoOf(Type)"/>
/// <seealso cref="GetEnumInfoOf{TWrapper}"/>
/// <seealso cref="GetEnumInfoOf(Type)"/>
public TypeMemberSetBase GetTypeInfoOf<TWrapper>() => Types[typeof(TWrapper)];
public TypeMemberSetBase GetTypeInfoOf<TWrapper>() => GetTypeInfoOf(typeof(TWrapper));

/// <summary>
/// <paramref name="wrapperType"/> に指定したラッパー型の情報を取得します。
Expand All @@ -95,37 +101,38 @@ private BveTypeSet(IEnumerable<TypeMemberSetBase> types, Version profileVersion)
/// <seealso cref="GetClassInfoOf(Type)"/>
/// <seealso cref="GetEnumInfoOf{TWrapper}"/>
/// <seealso cref="GetEnumInfoOf(Type)"/>
public TypeMemberSetBase GetTypeInfoOf(Type wrapperType) => Types[wrapperType];
public TypeMemberSetBase GetTypeInfoOf(Type wrapperType)
=> Types.TryGetValue(wrapperType, out TypeMemberSetBase typeInfo) ? typeInfo : Bridge[wrapperType];


/// <summary>
/// <typeparamref name="TWrapper"/> に指定したラッパー列挙型の情報を取得します。
/// </summary>
/// <typeparam name="TWrapper">ラッパー列挙型。</typeparam>
/// <returns><typeparamref name="TWrapper"/> に指定したラッパー列挙型の情報を表す <see cref="EnumMemberSet"/>。</returns>
public EnumMemberSet GetEnumInfoOf<TWrapper>() => (EnumMemberSet)Types[typeof(TWrapper)];
public EnumMemberSet GetEnumInfoOf<TWrapper>() => (EnumMemberSet)GetTypeInfoOf<TWrapper>();

/// <summary>
/// <paramref name="wrapperType"/> に指定したラッパー列挙型の情報を取得します。
/// </summary>
/// <param name="wrapperType">ラッパー列挙型。</param>
/// <returns><paramref name="wrapperType"/> に指定したラッパー列挙型の情報を表す <see cref="EnumMemberSet"/>。</returns>
public EnumMemberSet GetEnumInfoOf(Type wrapperType) => (EnumMemberSet)Types[wrapperType];
public EnumMemberSet GetEnumInfoOf(Type wrapperType) => (EnumMemberSet)GetTypeInfoOf(wrapperType);


/// <summary>
/// <typeparamref name="TWrapper"/> に指定したラッパークラスの情報を取得します。
/// </summary>
/// <typeparam name="TWrapper">ラッパークラス。</typeparam>
/// <returns><typeparamref name="TWrapper"/> に指定したラッパークラスの情報を表す <see cref="ClassMemberSet"/>。</returns>
public ClassMemberSet GetClassInfoOf<TWrapper>() => (ClassMemberSet)Types[typeof(TWrapper)];
public ClassMemberSet GetClassInfoOf<TWrapper>() => (ClassMemberSet)GetTypeInfoOf<TWrapper>();

/// <summary>
/// <paramref name="wrapperType"/> に指定したラッパークラスの情報を取得します。
/// </summary>
/// <param name="wrapperType">ラッパークラス。</param>
/// <returns><paramref name="wrapperType"/> に指定したラッパークラスの情報を表す <see cref="ClassMemberSet"/>。</returns>
public ClassMemberSet GetClassInfoOf(Type wrapperType) => (ClassMemberSet)Types[wrapperType];
public ClassMemberSet GetClassInfoOf(Type wrapperType) => (ClassMemberSet)GetTypeInfoOf(wrapperType);


/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@

namespace TypeWrapping
{
public static partial class WrapTypesXmlLoader
public partial class WrapTypeSet
{
private partial class MemberLoader
{
private class ElementParser
{
private class ResourceSet
{
private readonly ResourceLocalizer Localizer = ResourceLocalizer.FromResXOfType<ElementParser>(@"TypeWrapping\WrapTypesXmlLoader");
private readonly ResourceLocalizer Localizer = ResourceLocalizer.FromResXOfType<ElementParser>(@"TypeWrapping\WrapTypeSet");

[ResourceStringHolder(nameof(Localizer))] public Resource<string> OriginalFieldNotFound { get; private set; }
[ResourceStringHolder(nameof(Localizer))] public Resource<string> WrapperPropertyNotFound { get; private set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
Expand All @@ -10,15 +11,15 @@

namespace TypeWrapping
{
public static partial class WrapTypesXmlLoader
public partial class WrapTypeSet
{
private partial class MemberLoader
{
private class WrappedTypeResolver : TypeLoaderBase
{
private class ResourceSet
{
private readonly ResourceLocalizer Localizer = ResourceLocalizer.FromResXOfType<WrappedTypeResolver>(@"TypeWrapping\WrapTypesXmlLoader");
private readonly ResourceLocalizer Localizer = ResourceLocalizer.FromResXOfType<WrappedTypeResolver>(@"TypeWrapping\WrapTypeSet");

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

Expand All @@ -38,11 +39,14 @@ static WrappedTypeResolver()
}

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>>();

private readonly TypeParser WrapperTypeParser;
private readonly TypeParser OriginalTypeParser;

public int WrappedTypeCount => IsLoaded ? WrapperToOriginal.Count : throw new InvalidOperationException();
public IReadOnlyDictionary<Type, List<Type>> BridgingTypes => WrapperToBridgedWrapper;

public WrappedTypeResolver(XElement root, string targetNamespace,
TypeParser wrapperTypeParser, TypeParser originalTypeParser, IDictionary<Type, Type> additionalWrapperToOriginal) : base(root, targetNamespace)
Expand Down Expand Up @@ -74,6 +78,21 @@ private void Load(IEnumerable<XElement> elements, IEnumerable<XElement> parentCl
Type originalType = OriginalTypeParser.ParseSingleSpecializedTypeName(parentOriginalClassName + originalTypeName);

lock (WrapperToOriginal) WrapperToOriginal.Add(wrapperType, originalType);

XElement bridgesElement = element.Element(TargetNamespace + "Bridges");
if (!(bridgesElement is null))
{
IEnumerable<XElement> bridgeElements = bridgesElement.Elements(TargetNamespace + "Bridge");
foreach (XElement bridgeElement in bridgeElements)
{
string bridgedWrapperTypeName = GetWrapperTypeName(bridgeElement);
Type bridgedWrapperType = WrapperTypeParser.ParseSingleSpecializedTypeName(parentWrapperClassName + bridgedWrapperTypeName);

List<Type> bridgedTypes = WrapperToBridgedWrapper.GetOrAdd(wrapperType, _ => new List<Type>());
lock (bridgedTypes) bridgedTypes.Add(bridgedWrapperType);
lock (BridgedWrapperToWrapper) BridgedWrapperToWrapper.Add(bridgedWrapperType, wrapperType);
}
}
});
}

Expand All @@ -89,15 +108,13 @@ public Type GetOriginal(Type wrapper)
else if (wrapper.IsConstructedGenericType)
{
Type wrapperParent = wrapper.GetGenericTypeDefinition();
WrapperToOriginal.TryGetValue(wrapperParent, out Type originalParent);
originalParent = originalParent ?? wrapperParent;
Type originalParent = ParseSimpleType(wrapperParent);

Type[] wrapperChildren = wrapper.GetGenericArguments();
Type[] originalChildren = new Type[wrapperChildren.Length];
for (int i = 0; i < wrapperChildren.Length; i++)
{
WrapperToOriginal.TryGetValue(wrapperChildren[i], out Type originalChild);
originalChildren[i] = originalChild ?? wrapperChildren[i];
originalChildren[i] = ParseSimpleType(wrapperChildren[i]);
}

Type result = originalParent.MakeGenericType(originalChildren);
Expand All @@ -108,17 +125,29 @@ public Type GetOriginal(Type wrapper)
if (!wrapper.IsArray || wrapper.Name.Contains("*")) throw new NotSupportedException(Resources.Value.ElementTypesButArrayNotSupported.Value);

Type wrapperElement = wrapper.GetElementType();
WrapperToOriginal.TryGetValue(wrapperElement, out Type originalElement);
originalElement = originalElement ?? wrapperElement;
Type originalElement = ParseSimpleType(wrapperElement);

int rank = wrapper.GetArrayRank();
Type result = rank == 1 ? originalElement.MakeArrayType() : originalElement.MakeArrayType(rank);
return result;
}
else
{
WrapperToOriginal.TryGetValue(wrapper, out Type result);
return result ?? wrapper;
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;
}
}

Expand All @@ -140,13 +169,13 @@ public Type GetOriginal(Type wrapper)
}


private static string GetWrapperTypeName(XElement element) => GetTypeName(element, "Wrapper");
private static string GetOriginalTypeName(XElement element) => GetTypeName(element, "Original");
private static string GetWrapperTypeName(XElement element) => GetAttributeValue(element, "Wrapper");
private static string GetOriginalTypeName(XElement element) => GetAttributeValue(element, "Original");

private static string GetTypeName(XElement element, string attributeName)
private static string GetAttributeValue(XElement element, string attributeName)
{
string typeName = (string)element.Attribute(attributeName);
return typeName;
string attributeValue = (string)element.Attribute(attributeName);
return attributeValue;
}


Expand All @@ -159,7 +188,7 @@ private static string GetParentClassName(IEnumerable<XElement> parentClassElemen

foreach (XElement parentClassElement in parentClassElements)
{
string wrapperTypeName = GetTypeName(parentClassElement, attributeName);
string wrapperTypeName = GetAttributeValue(parentClassElement, attributeName);

parentClassNameBuilder.Append(wrapperTypeName);
parentClassNameBuilder.Append("+");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@

namespace TypeWrapping
{
public static partial class WrapTypesXmlLoader
public partial class WrapTypeSet
{
private partial class MemberLoader : TypeLoaderBase
{
private class ResourceSet
{
private readonly ResourceLocalizer Localizer = ResourceLocalizer.FromResXOfType<MemberLoader>(@"TypeWrapping\WrapTypesXmlLoader");
private readonly ResourceLocalizer Localizer = ResourceLocalizer.FromResXOfType<MemberLoader>(@"TypeWrapping\WrapTypeSet");

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

Expand All @@ -38,6 +38,9 @@ static MemberLoader()

public List<TypeMemberSetBase> Types { get; }

private readonly Dictionary<Type, TypeMemberSetBase> BridgeSource;
public TypeBridge Bridge { get; }

private readonly TypeParser WrapperTypeParser;
private readonly WrappedTypeResolver Resolver;

Expand All @@ -50,6 +53,8 @@ public MemberLoader(XElement root, string targetNamespace,
Resolver.LoadAll();

Types = new List<TypeMemberSetBase>(Resolver.WrappedTypeCount);
BridgeSource = new Dictionary<Type, TypeMemberSetBase>(Resolver.BridgingTypes.Sum(x => x.Value.Count));
Bridge = new TypeBridge(BridgeSource);
}

protected override void LoadDelegates(IEnumerable<XElement> delegateElements, IEnumerable<XElement> parentClassElements)
Expand All @@ -59,6 +64,7 @@ protected override void LoadDelegates(IEnumerable<XElement> delegateElements, IE
(Type wrapperType, Type originalType) = Resolver.Resolve(element, parentClassElements);
DelegateMemberSet members = new DelegateMemberSet(wrapperType, originalType);

LoadBridges(members);
return members;
});

Expand All @@ -72,6 +78,7 @@ protected override void LoadEnums(IEnumerable<XElement> enumElements, IEnumerabl
(Type wrapperType, Type originalType) = Resolver.Resolve(element, parentClassElements);
EnumMemberSet members = new EnumMemberSet(wrapperType, originalType);

LoadBridges(members);
return members;
});

Expand Down Expand Up @@ -179,11 +186,23 @@ protected override void LoadClasses(IEnumerable<XElement> classElements, IEnumer
}

ClassMemberSet members = new ClassMemberSet(wrapperType, originalType, propertyGetters, propertySetters, fields, events, constructors, methods);

LoadBridges(members);
return members;
});

Types.AddRange(loadedTypes);
}

private void LoadBridges(TypeMemberSetBase target)
{
if (!Resolver.BridgingTypes.TryGetValue(target.WrapperType, out List<Type> bridgedTypes)) return;

foreach (Type bridgedType in bridgedTypes)
{
BridgeSource.Add(bridgedType, target);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace TypeWrapping
{
public static partial class WrapTypesXmlLoader
public partial class WrapTypeSet
{
private abstract class TypeLoaderBase
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@

namespace TypeWrapping
{
public static partial class WrapTypesXmlLoader
public partial class WrapTypeSet
{
private class ResourceSet
{
private readonly ResourceLocalizer Localizer = ResourceLocalizer.FromResXOfType(typeof(WrapTypesXmlLoader), @"TypeWrapping\WrapTypesXmlLoader");
private readonly ResourceLocalizer Localizer = ResourceLocalizer.FromResXOfType(typeof(WrapTypeSet), @"TypeWrapping\WrapTypeSet");

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

Expand All @@ -28,14 +28,23 @@ public ResourceSet()

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

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

public static List<TypeMemberSetBase> LoadFile(Stream docStream, Stream schemaStream,
public IEnumerable<TypeMemberSetBase> Types { get; }
public TypeBridge Bridge { get; }

private WrapTypeSet(IEnumerable<TypeMemberSetBase> types, TypeBridge bridge)
{
Types = types;
Bridge = bridge;
}

public static WrapTypeSet LoadXml(Stream docStream, Stream schemaStream,
IEnumerable<Type> wrapperTypes, IEnumerable<Type> originalTypes, IDictionary<Type, Type> additionalWrapperToOriginal)
{
XDocument doc = XDocument.Load(docStream);
Expand All @@ -54,7 +63,7 @@ public static List<TypeMemberSetBase> LoadFile(Stream docStream, Stream schemaSt
MemberLoader loader = new MemberLoader(root, targetNamespace, wrapperTypeParser, originalTypeParser, additionalWrapperToOriginal);
loader.LoadAll();

return loader.Types;
return new WrapTypeSet(loader.Types, loader.Bridge);
}

private static void SchemaValidation(object sender, ValidationEventArgs e)
Expand Down
Loading

0 comments on commit 65597ed

Please sign in to comment.