void QCALLTYPE COMDynamicWrite::TermCreateClass(QCall::ModuleHandle pModule, INT32 tk, QCall::ObjectHandleOnStack retType) { QCALL_CONTRACT; TypeHandle typeHnd; BEGIN_QCALL; _ASSERTE(pModule->GetReflectionModule()->GetClassWriter()); // Use the same service, regardless of whether we are generating a normal // class, or the special class for the module that holds global functions // & methods. pModule->GetReflectionModule()->AddClass(tk); // manually load the class if it is not the global type if (!IsNilToken(tk)) { TypeKey typeKey(pModule, tk); typeHnd = pModule->GetClassLoader()->LoadTypeHandleForTypeKey(&typeKey, TypeHandle()); } if (!typeHnd.IsNull()) { GCX_COOP(); retType.Set(typeHnd.GetManagedClassObject()); } END_QCALL; return; }
INT32 QCALLTYPE COMDynamicWrite::DefineType(QCall::ModuleHandle pModule, LPCWSTR wszFullName, INT32 tkParent, INT32 attributes, INT32 tkEnclosingType, INT32 * pInterfaceTokens) { QCALL_CONTRACT; mdTypeDef classE = mdTokenNil; BEGIN_QCALL; RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter(); _ASSERTE(pRCW); HRESULT hr; if (RidFromToken(tkEnclosingType)) { // defining nested type hr = pRCW->GetEmitter()->DefineNestedType(wszFullName, attributes, tkParent == 0 ? mdTypeRefNil : tkParent, (mdToken *)pInterfaceTokens, tkEnclosingType, &classE); } else { // top level type hr = pRCW->GetEmitter()->DefineTypeDef(wszFullName, attributes, tkParent == 0 ? mdTypeRefNil : tkParent, (mdToken *)pInterfaceTokens, &classE); } if (hr == META_S_DUPLICATE) { COMPlusThrow(kArgumentException, W("Argument_DuplicateTypeName")); } if (FAILED(hr)) { _ASSERTE(hr == E_OUTOFMEMORY || !"DefineTypeDef Failed"); COMPlusThrowHR(hr); } AllocMemTracker amTracker; pModule->GetClassLoader()->AddAvailableClassDontHaveLock(pModule, classE, &amTracker); amTracker.SuppressRelease(); END_QCALL; return (INT32)classE; }
FCIMPLEND //************************************************** // LoadInMemoryTypeByName // Explicitly loading an in memory type // <TODO>@todo: this function is not dealing with nested type correctly yet. // We will need to parse the full name by finding "+" for enclosing type, etc.</TODO> //************************************************** void QCALLTYPE COMModule::LoadInMemoryTypeByName(QCall::ModuleHandle pModule, LPCWSTR wszFullName) { QCALL_CONTRACT; TypeHandle typeHnd; BEGIN_QCALL; if (!pModule->IsReflection()) COMPlusThrow(kNotSupportedException, W("NotSupported_NonReflectedType")); RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter(); _ASSERTE(pRCW); // it is ok to use public import API because this is a dynamic module anyway. We are also receiving Unicode full name as // parameter. IMetaDataImport * pImport = pRCW->GetRWImporter(); if (wszFullName == NULL) IfFailThrow( E_FAIL ); // look up the handle mdTypeDef td; HRESULT hr = pImport->FindTypeDefByName(wszFullName, mdTokenNil, &td); if (FAILED(hr)) { if (hr != CLDB_E_RECORD_NOTFOUND) COMPlusThrowHR(hr); // Get the UTF8 version of strFullName MAKE_UTF8PTR_FROMWIDE(szFullName, wszFullName); pModule->GetAssembly()->ThrowTypeLoadException(szFullName, IDS_CLASSLOAD_GENERAL); } TypeKey typeKey(pModule, td); typeHnd = pModule->GetClassLoader()->LoadTypeHandleForTypeKey(&typeKey, TypeHandle()); END_QCALL; return; }
//************************************************** // GetTypeRef // This function will return the type token given full qual name. If the type // is defined locally, we will return the TypeDef token. Or we will return a TypeRef token // with proper resolution scope calculated. // wszFullName is escaped (TYPE_NAME_RESERVED_CHAR). It should not be byref or contain enclosing type name, // assembly name, and generic argument list. //************************************************** mdTypeRef QCALLTYPE COMModule::GetTypeRef(QCall::ModuleHandle pModule, LPCWSTR wszFullName, QCall::ModuleHandle pRefedModule, LPCWSTR wszRefedModuleFileName, INT32 tkResolutionArg) { QCALL_CONTRACT; mdTypeRef tr = 0; BEGIN_QCALL; RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter(); _ASSERTE(pRCW); IMetaDataEmit * pEmit = pRCW->GetEmitter(); IMetaDataImport * pImport = pRCW->GetRWImporter(); if (wszFullName == NULL) { COMPlusThrow(kArgumentNullException, W("ArgumentNull_String")); } InlineSString<128> ssNameUnescaped; LPCWSTR wszTemp = wszFullName; WCHAR c; while(0 != (c = *wszTemp++)) { if ( c == W('\\') && IsTypeNameReservedChar(*wszTemp) ) { ssNameUnescaped.Append(*wszTemp++); } else { _ASSERTE( ! IsTypeNameReservedChar(c) ); ssNameUnescaped.Append(c); } } LPCWSTR wszFullNameUnescaped = ssNameUnescaped.GetUnicode(); Assembly * pThisAssembly = pModule->GetClassLoader()->GetAssembly(); Assembly * pRefedAssembly = pRefedModule->GetClassLoader()->GetAssembly(); if (pModule == pRefedModule) { // referenced type is from the same module so we must be able to find a TypeDef. IfFailThrow(pImport->FindTypeDefByName( wszFullNameUnescaped, RidFromToken(tkResolutionArg) ? tkResolutionArg : mdTypeDefNil, &tr)); } else { mdToken tkResolution = mdTokenNil; if (RidFromToken(tkResolutionArg)) { // reference to nested type tkResolution = tkResolutionArg; } else { // reference to top level type if ( pThisAssembly != pRefedAssembly ) { SafeComHolderPreemp<IMetaDataAssemblyEmit> pAssemblyEmit; // Generate AssemblyRef IfFailThrow( pEmit->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) ); tkResolution = pThisAssembly->AddAssemblyRef(pRefedAssembly, pAssemblyEmit); // Add the assembly ref token and the manifest module it is referring to this module's rid map. // This is needed regardless of whether the dynamic assembly has run access. Even in Save-only // or Refleciton-only mode, CreateType() of the referencing type may still need the referenced // type to be resolved and loaded, e.g. if the referencing type is a subclass of the referenced type. // // Don't cache if there is assembly associated with the token already. The assembly ref resolution // can be ambiguous because of reflection emit does not require unique assembly names. // We always let the first association win. Ideally, we would disallow this situation by throwing // exception, but that would be a breaking change. if(pModule->LookupAssemblyRef(tkResolution) == NULL) { pModule->ForceStoreAssemblyRef(tkResolution, pRefedAssembly); } } else { _ASSERTE(pModule != pRefedModule); _ASSERTE(wszRefedModuleFileName != NULL); // Generate ModuleRef IfFailThrow(pEmit->DefineModuleRef(wszRefedModuleFileName, &tkResolution)); } } IfFailThrow( pEmit->DefineTypeRefByName(tkResolution, wszFullNameUnescaped, &tr) ); } END_QCALL; return tr; }