// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
+using System.Diagnostics;
using CultureInfo = System.Globalization.CultureInfo;
using System.Security;
using System.IO;
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern int GetToken(RuntimeAssembly assembly);
+
+ public sealed override Type[] GetForwardedTypes()
+ {
+ List<Type> types = new List<Type>();
+ List<Exception> exceptions = new List<Exception>();
+
+ MetadataImport scope = GetManifestModule(GetNativeHandle()).MetadataImport;
+ scope.Enum(MetadataTokenType.ExportedType, 0, out MetadataEnumResult enumResult);
+ for (int i = 0; i < enumResult.Length; i++)
+ {
+ MetadataToken mdtExternalType = enumResult[i];
+ Type type = null;
+ Exception exception = null;
+ ObjectHandleOnStack pType = JitHelpers.GetObjectHandleOnStack(ref type);
+ try
+ {
+ GetForwardedType(this, mdtExternalType, pType);
+ if (type == null)
+ continue; // mdtExternalType was not a forwarder entry.
+ }
+ catch (Exception e) when (IsLoaderException(e))
+ {
+ type = null;
+ exception = e;
+ }
+
+ Debug.Assert((type != null) != (exception != null)); // Exactly one of these must be non-null.
+
+ if (type != null)
+ {
+ types.Add(type);
+ AddPublicNestedTypes(type, types, exceptions);
+ }
+ else
+ {
+ exceptions.Add(exception);
+ }
+ }
+
+ if (exceptions.Count != 0)
+ {
+ int numTypes = types.Count;
+ int numExceptions = exceptions.Count;
+ types.AddRange(new Type[numExceptions]); // add one null Type for each exception.
+ exceptions.InsertRange(0, new Exception[numTypes]); // align the Exceptions with the null Types.
+ throw new ReflectionTypeLoadException(types.ToArray(), exceptions.ToArray());
+ }
+
+ return types.ToArray();
+ }
+
+ private static void AddPublicNestedTypes(Type type, List<Type> types, List<Exception> exceptions)
+ {
+ Type[] nestedTypes;
+ try
+ {
+ nestedTypes = type.GetNestedTypes(BindingFlags.Public);
+ }
+ catch (Exception e) when (IsLoaderException(e))
+ {
+ exceptions.Add(e);
+ return;
+ }
+ foreach (Type nestedType in nestedTypes)
+ {
+ types.Add(nestedType);
+ AddPublicNestedTypes(nestedType, types, exceptions);
+ }
+ }
+
+ private static bool IsLoaderException(Exception e)
+ {
+ return e is FileLoadException || e is FileNotFoundException || e is TypeLoadException || e is IOException || e is UnauthorizedAccessException;
+ }
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static unsafe extern void GetForwardedType(RuntimeAssembly assembly, MetadataToken mdtExternalType, ObjectHandleOnStack type);
}
}
return;
}
+void QCALLTYPE AssemblyNative::GetForwardedType(QCall::AssemblyHandle pAssembly, mdToken mdtExternalType, QCall::ObjectHandleOnStack retType)
+{
+ CONTRACTL
+ {
+ QCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ BEGIN_QCALL;
+
+ HRESULT hr;
+ LPCSTR pszNameSpace;
+ LPCSTR pszClassName;
+ mdToken mdImpl;
+
+ Assembly * pAsm = pAssembly->GetAssembly();
+ Module *pManifestModule = pAsm->GetManifestModule();
+ IfFailThrow(pManifestModule->GetMDImport()->GetExportedTypeProps(mdtExternalType, &pszNameSpace, &pszClassName, &mdImpl, NULL, NULL));
+ if (TypeFromToken(mdImpl) == mdtAssemblyRef)
+ {
+ NameHandle typeName(pszNameSpace, pszClassName);
+ typeName.SetTypeToken(pManifestModule, mdtExternalType);
+ TypeHandle typeHnd = pAsm->GetLoader()->LoadTypeHandleThrowIfFailed(&typeName);
+ {
+ GCX_COOP();
+ retType.Set(typeHnd.GetManagedClassObject());
+ }
+ }
+
+ END_QCALL;
+
+ return;
+}
+
FCIMPL1(FC_BOOL_RET, AssemblyNative::IsDynamic, AssemblyBaseObject* pAssemblyUNSAFE)
{
FCALL_CONTRACT;
static
void QCALLTYPE GetType(QCall::AssemblyHandle pAssembly, LPCWSTR wszName, BOOL bThrowOnError, BOOL bIgnoreCase, QCall::ObjectHandleOnStack retType, QCall::ObjectHandleOnStack keepAlive);
-
+
+ static
+ void QCALLTYPE AssemblyNative::GetForwardedType(QCall::AssemblyHandle pAssembly, mdToken mdtExternalType, QCall::ObjectHandleOnStack retType);
+
static
INT32 QCALLTYPE GetManifestResourceInfo(QCall::AssemblyHandle pAssembly, LPCWSTR wszName, QCall::ObjectHandleOnStack retAssembly, QCall::StringHandleOnStack retFileName, QCall::StackCrawlMarkHandle stackMark);
FCFuncElement("FCallIsDynamic", AssemblyNative::IsDynamic)
FCFuncElement("nLoad", AssemblyNative::Load)
QCFuncElement("GetType", AssemblyNative::GetType)
+ QCFuncElement("GetForwardedType", AssemblyNative::GetForwardedType)
QCFuncElement("GetManifestResourceInfo", AssemblyNative::GetManifestResourceInfo)
QCFuncElement("GetModules", AssemblyNative::GetModules)
QCFuncElement("GetModule", AssemblyNative::GetModule)