protected virtual IType MapType(IType sourceType)
{
if (sourceType == null)
{
return null;
}
// Strip reference types
if (sourceType.IsByRef)
{
return MapType(sourceType.GetElementType());
}
// Map generic parameter to corresponding argument
IGenericParameter gp = sourceType as IGenericParameter;
if (null != gp && _map.ContainsKey(gp))
{
return _map[gp];
}
// Map open constructed type using generic parameters to closed constructed type
// using corresponding arguments
if (null != sourceType.ConstructedInfo)
{
IType[] mappedArguments = Array.ConvertAll<IType, IType>(
sourceType.ConstructedInfo.GenericArguments,
MapType);
IType mapped = sourceType.ConstructedInfo.
GenericDefinition.GenericInfo.
ConstructType(mappedArguments);
return mapped;
}
// TODO: Map nested types
// GenericType[of T].NestedType => GenericType[of int].NestedType
// Map array types
IArrayType array = (sourceType as IArrayType);
if (array != null)
{
IType elementType = array.GetElementType();
IType mappedElementType = MapType(elementType);
if (mappedElementType != elementType)
{
return _tss.GetArrayType(mappedElementType, array.GetArrayRank());
}
}
// Map callable types
ICallableType callable = sourceType as ICallableType;
if (callable != null && EntityNeedsMapping(callable))
{
CallableSignature signature = callable.GetSignature();
IType returnType = MapType(signature.ReturnType);
IParameter[] parameters = Map(signature.Parameters);
CallableSignature mappedSignature = new CallableSignature(
parameters, returnType, signature.AcceptVarArgs);
return _tss.GetCallableType(mappedSignature);
}
// If source type doesn't require mapping, return it as is
return sourceType;
}