Last active
August 29, 2015 14:25
-
-
Save controlflow/53c4320364eae642be4e to your computer and use it in GitHub Desktop.
Simple System.Type visitor to traverse and replace types
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using JetBrains.Annotations; | |
namespace Smth { | |
[PublicAPI] | |
public abstract class ReflectionTypeVisitor<T> { | |
public virtual T VisitSimpleType(Type type) => default(T); | |
public virtual T VisitConstructedType([NotNull] Type typeDefinition, [NotNull] Type[] typeArguments) => default(T); | |
public virtual T VisitTypeParameterType([NotNull] Type typeParameter) => default(T); | |
public virtual T VisitArrayType([NotNull] Type arrayType) => default(T); | |
public virtual T VisitByRefType([NotNull] Type referenceType) => default(T); | |
public virtual T VisitPointerType([NotNull] Type pointerType) => default(T); | |
protected T Accept([NotNull] Type type) { | |
if (type.IsArray) return VisitArrayType(type); | |
if (type.IsByRef) return VisitByRefType(type); | |
if (type.IsPointer) return VisitPointerType(type); | |
if (type.IsGenericParameter) return VisitTypeParameterType(type); | |
if (type.IsConstructedGenericType) { | |
return VisitConstructedType( | |
typeDefinition: type.GetGenericTypeDefinition(), | |
typeArguments: type.GetGenericArguments()); | |
} | |
return VisitSimpleType(type); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using JetBrains.Annotations; | |
namespace Smth { | |
[PublicAPI] | |
public abstract class RewritingTypeVisitor : ReflectionTypeVisitor<Type> { | |
public override Type VisitSimpleType(Type type) => null; | |
public override Type VisitTypeParameterType(Type typeParameter) => null; | |
public override Type VisitConstructedType(Type typeDefinition, Type[] typeArguments) { | |
var newTypeDefinition = Accept(typeDefinition); | |
Type[] newTypeArguments = null; | |
for (var index = 0; index < typeArguments.Length; index++) { | |
var newTypeArgument = Accept(typeArguments[index]); | |
if (newTypeArgument == null) continue; | |
if (newTypeArguments == null) { | |
newTypeArguments = new Type[typeArguments.Length]; | |
Array.Copy(typeArguments, newTypeArguments, typeArguments.Length); | |
} | |
newTypeArguments[index] = newTypeArgument; | |
} | |
if (newTypeDefinition == null && newTypeArguments == null) return null; | |
var definition = newTypeDefinition ?? typeDefinition; | |
return definition.MakeGenericType(newTypeArguments ?? typeArguments); | |
} | |
public override Type VisitArrayType(Type arrayType) { | |
var elementType = arrayType.GetElementType(); | |
var newElementType = Accept(elementType); | |
if (newElementType == null) return null; | |
if (arrayType == elementType.MakeArrayType()) { // SZArray check | |
return newElementType.MakeArrayType(); | |
} | |
return newElementType.MakeArrayType(arrayType.GetArrayRank()); | |
} | |
public override Type VisitByRefType(Type referenceType) { | |
var newElementType = Accept(referenceType.GetElementType()); | |
return newElementType?.MakeByRefType(); | |
} | |
public override Type VisitPointerType(Type pointerType) { | |
var newElementType = Accept(pointerType.GetElementType()); | |
return newElementType?.MakePointerType(); | |
} | |
[NotNull, Pure] | |
public Type Rewrite([NotNull] Type type) { | |
return Accept(type) ?? type; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private sealed class ReplaceTypeVisitor : RewritingTypeVisitor { | |
[NotNull] private readonly Dictionary<Type, Type> myTypesMap; | |
public ReplaceTypeVisitor([NotNull] Dictionary<Type, Type> typesMap) { | |
myTypesMap = typesMap; | |
} | |
public override Type VisitSimpleType(Type type) { | |
Type value; | |
myTypesMap.TryGetValue(type, out value); | |
return value; | |
} | |
public override Type VisitTypeParameterType(Type typeParameter) { | |
return VisitSimpleType(typeParameter); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment