/// <summary>
/// Maps a type involving generic parameters to the corresponding type after substituting concrete
/// arguments for generic parameters.
/// </summary>
/// <remarks>
/// If the source type is a generic parameter, it is mapped to the corresponding argument.
/// If the source type is an open generic type using any of the specified generic parameters, it
/// is mapped to a closed constructed type based on the specified arguments.
/// TODO: complete this
/// </remarks>
public IType MapType(IType sourceType)
{
if (sourceType == null)
{
return(null);
}
// If sourceType is a reference type, map its element type
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.GenericTypeInfo)
{
IType[] mappedArguments = Array.ConvertAll <IType, IType>(
sourceType.GenericTypeInfo.GenericArguments,
MapType);
IType mapped = sourceType.GenericTypeInfo.
GenericDefinition.GenericTypeDefinitionInfo.
MakeGenericType(mappedArguments);
return(mapped);
}
// 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)
{
CallableSignature signature = callable.GetSignature();
IType returnType = MapType(signature.ReturnType);
IParameter[] parameters = Array.ConvertAll <IParameter, IParameter>(
signature.Parameters,
delegate(IParameter p) { return(new MappedParameter(_tss, (ExternalParameter)p, this)); });
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);
}