/// <summary>
        /// Resolves a type reference.
        /// </summary>
        /// <param name="typeRef">The type reference to resolve.</param>
        /// <param name="assembly">The assembly in which the reference occurs.</param>
        /// <param name="enclosingMember">
        /// The generic member that references a particular type. If non-null, type
        /// parameters are resolved from this member.
        /// </param>
        /// <param name="useStandins">
        /// A Boolean that specifies if stand-ins should be used for generic parameters.
        /// </param>
        /// <returns>The type referred to by the reference.</returns>
        private IType Resolve(
            TypeReference typeRef,
            ClrAssembly assembly,
            IGenericMember enclosingMember,
            bool useStandins)
        {
            if (typeRef is TypeSpecification)
            {
                var typeSpec = (TypeSpecification)typeRef;
                var elemType = Resolve(typeSpec.ElementType, assembly, enclosingMember, useStandins);
                if (typeSpec is GenericInstanceType)
                {
                    var genInstType = (GenericInstanceType)typeSpec;
                    return(elemType.MakeRecursiveGenericType(
                               genInstType.GenericArguments.Select(
                                   arg => TypeHelpers.BoxIfReferenceType(
                                       Resolve(arg, assembly, enclosingMember, useStandins)))
                               .ToArray()));
                }
                else if (typeSpec is Mono.Cecil.PointerType)
                {
                    return(TypeHelpers.BoxIfReferenceType(elemType)
                           .MakePointerType(PointerKind.Transient));
                }
                else if (typeSpec is ByReferenceType)
                {
                    return(TypeHelpers.BoxIfReferenceType(elemType)
                           .MakePointerType(PointerKind.Reference));
                }
                else if (typeSpec is Mono.Cecil.ArrayType)
                {
                    var   arraySpec = (Mono.Cecil.ArrayType)typeSpec;
                    var   boxedElem = TypeHelpers.BoxIfReferenceType(elemType);
                    IType arrayType;
                    if (TypeEnvironment.TryMakeArrayType(
                            boxedElem,
                            arraySpec.Rank,
                            out arrayType))
                    {
                        return(arrayType);
                    }
                    else
                    {
                        throw new NotSupportedException(
                                  "Cannot resolve array specification '" +
                                  typeSpec.ToString() + "' because the type environment " +
                                  "does not support arrays with that element type and rank.");
                    }
                }
                else
                {
                    throw new NotSupportedException(
                              "Unsupported kind of type specification '" +
                              typeSpec.ToString() + "'.");
                }
            }
            else if (typeRef is GenericParameter)
            {
                var genericParam = (GenericParameter)typeRef;
                if (useStandins)
                {
                    return(ClrGenericParameterStandin.Create(
                               genericParam.Type,
                               genericParam.Position,
                               genericParam.HasReferenceTypeConstraint));
                }
                else if (genericParam.DeclaringMethod == null)
                {
                    var declType = enclosingMember is IType
                        ? (IType)enclosingMember
                        : enclosingMember is IMethod
                            ? ((IMethod)enclosingMember).ParentType
                            : Resolve(
                        genericParam.DeclaringType,
                        assembly,
                        enclosingMember,
                        useStandins);

                    return(declType.GetRecursiveGenericParameters()[genericParam.Position]);
                }
                else
                {
                    var declMethod = enclosingMember is IMethod
                        ? (IMethod)enclosingMember
                        : Resolve(genericParam.DeclaringMethod, assembly);
                    return(declMethod.GenericParameters[genericParam.Position]);
                }
            }
            else
            {
                if (typeRef.DeclaringType != null)
                {
                    var declType = Resolve(
                        typeRef.DeclaringType,
                        assembly,
                        enclosingMember,
                        useStandins);

                    var nestedTypes = GetTypeResolver(assembly).ResolveNestedTypes(
                        declType,
                        NameConversion.ParseSimpleName(typeRef.Name));
                    return(PickSingleResolvedType(typeRef, nestedTypes));
                }

                var scope = typeRef.Scope;

                if (scope == null)
                {
                    throw new ResolutionException(typeRef);
                }

                switch (scope.MetadataScopeType)
                {
                case MetadataScopeType.AssemblyNameReference:
                    return(FindInAssembly(typeRef, Resolve((AssemblyNameReference)scope)));

                case MetadataScopeType.ModuleDefinition:
                case MetadataScopeType.ModuleReference:
                default:
                    return(FindInAssembly(typeRef, assembly));
                }
            }
        }