本文提供此 API 參考文件的補充備註。
GetType(String, Func<AssemblyName,Assembly>, Func<Assembly,String,Boolean,Type>, Boolean, Boolean)使用 方法多載及其相關聯的多載 (GetType(String, Func<AssemblyName,Assembly>, Func<Assembly,String,Boolean,Type>)和 GetType(String, Func<AssemblyName,Assembly>, Func<Assembly,String,Boolean,Type>, Boolean)),以更有彈性的GetType實作取代方法的默認實作。 藉由提供您自己的方法來解析類型名稱和包含它們的元件名稱,您可以執行下列動作:
- 控制從中載入類型的元件版本。
- 提供另一個位置來尋找不包含元件名稱的類型名稱。
- 使用部分元件名稱載入元件。
- 傳回 Common Language Runtime (CLR) 未建立的子類別 System.Type 。
例如,在版本容錯序列化中,此方法可讓您使用部分名稱來搜尋「最佳匹配」的組件。 方法的其他多載 GetType 需要元件限定的類型名稱,其中包含版本號碼。
型別系統的替代實作可能需要傳回不是由 CLR 建立的System.Type子類別,而方法的其他多載所傳回的所有類型都是執行階段類型。
使用量注意事項
這個多載方法及其相關聯的多載會剖析 typeName 為型別的名稱和元件的名稱,然後解析這些名稱。 元件名稱的解析會在類型名稱解析之前發生,因為必須在元件的內容中解析類型名稱。
備註
如果您不熟悉元件限定類型名稱的概念,請參閱 AssemblyQualifiedName 屬性。
如果 typeName 不是元件限定名稱,則會略過元件解析。 在 mscorlib.dll/System.Private.CoreLib.dll 或目前執行的元件的上下文中,可以解析未限定的類型名稱,或者您可以選擇性地於 typeResolver 參數中提供元件。 包含或省略組件名稱在不同類型名稱解析中的效果會顯示為 混合名稱解析 區段中的表格。
一般使用注意事項:
請勿將方法傳遞給
assemblyResolver或typeResolver,如果它們來自未知或未受信任的呼叫者。 只使用您提供或熟悉的方法。謹慎
使用來自未知或未受信任呼叫端的方法可能會導致惡意代碼的許可權提升。
如果您省略
assemblyResolver和/或typeResolver參數,參數的值throwOnError會傳遞至執行預設解析的方法。如果
throwOnError是true,這個方法會在 TypeLoadException 傳回typeResolver時擲回null,當 FileNotFoundException 傳回assemblyResolver時擲回null。這個方法不會攔截由
assemblyResolver和typeResolver擲回的例外狀況。 您負責處理解析方法擲回的任何例外狀況。
解析組件
方法 assemblyResolver 接收由解析包含於 AssemblyName 的字串組件名稱所產生的 typeName 物件。 如果 typeName 不包含元件名稱, assemblyResolver 則不會呼叫 ,而且 null 會傳遞至 typeResolver。
如果未提供assemblyResolver,則會使用標準組件探查來找出組件。 如果提供 assemblyResolver,則 GetType 方法不會進行標準探測。在此情況下,您必須確保您的 assemblyResolver 能夠處理您傳遞給它的所有組件。
如果無法解析組件,方法 assemblyResolver 應傳回 null 。 如果 assemblyResolver 回傳 null,則不會呼叫 typeResolver,並且不會進一步處理。此外,如果 throwOnError 為 true,則會拋出 FileNotFoundException。
AssemblyName如果傳遞至 assemblyResolver 的 是部分名稱,則其一或多個部分為 null。 例如,如果沒有版本,則 Version 屬性為 null。 如果 Version 屬性、CultureInfo 屬性和 GetPublicKeyToken 方法全都傳回 null,那麼只提供了元件的簡單名稱。
assemblyResolver方法可以使用或忽略元件名稱的所有部分。
不同元件解析選項的影響已顯示在混合名稱解析區段的表格中,涵蓋簡單和元件限定的類型名稱。
解析類型
如果沒有 typeName 指定元件名稱,typeResolver 則一律會被呼叫。 如果 typeName 指定元件名稱, typeResolver 只有在成功解析元件名稱時,才會呼叫 。 如果 assemblyResolver 或標準元件探查傳 null回 , typeResolver 則不會呼叫 。
方法 typeResolver 會接收三個自變數:
- 要搜尋的組件是
null,如果typeName不包含組件名稱,則不執行搜尋。 - 型別的簡單名稱。 在巢狀類型的情況下,這是最外層的包含類型。 在泛型型別的情況下,這是泛型型別的簡單名稱。
- 布爾值,表示
true要忽略類型名稱的案例。
實作會決定使用這些自變數的方式。
typeResolver如果方法無法解析類型,則應該會傳回 null 。 如果 typeResolver 傳回 null 且 throwOnError 為 true,那麼 GetType 多載會擲出 TypeLoadException。
不同類型解析方式的效果會以表格形式顯示在 混合名稱解析 區段中,以解析簡單和元件限定的類型名稱。
解析巢狀類型
如果 typeName 是巢狀類型,則只會將包含型別的最外層名稱傳遞至 typeResolver。 傳回此類型時 typeResolver , GetNestedType 方法會以遞歸方式呼叫,直到解析最內部的巢狀類型為止。
解析泛型類型
GetType會以遞歸方式呼叫 來解析泛型型別:首先解析泛型型別本身,然後解析其型別自變數。 如果類型自變數是泛型, GetType 則會以遞歸方式呼叫 ,以解析其類型自變數等等。
assemblyResolver和 typeResolver 的組合必須能夠解析此遞歸的所有層級。 例如,假設您提供 assemblyResolver 控制載入的 MyAssembly。 假設您想要解析泛型類型 Dictionary<string, MyType> (Dictionary(Of String, MyType) 在 Visual Basic 中)。 您可能會傳遞下列泛型名稱:
"System.Collections.Generic.Dictionary`2[System.String,[MyNamespace.MyType, MyAssembly]]"
請注意, MyType 這是唯一的元件限定型別自變數。
Dictionary<TKey,TValue> 和 String 類別的名稱不是元件限定的。 您的 typeResolver 必須能夠處理組件或 null,因為它將會接收到 null,適用於 Dictionary<TKey,TValue> 和 String。 它可以藉由呼叫接受字串的GetType方法的多載版本來處理該案例,因為這兩個未限定的型別名稱都在 mscorlib.dll/System.Private.CoreLib.dll中:
Type t = Type.GetType(test,
(aName) => aName.Name == "MyAssembly" ?
Assembly.LoadFrom(@".\MyPath\v5.0\MyAssembly.dll") : null,
(assem, name, ignore) => assem == null ?
Type.GetType(name, false, ignore) :
assem.GetType(name, false, ignore)
);
let t =
Type.GetType(test,
(fun aName ->
if aName.Name = "MyAssembly" then
Assembly.LoadFrom @".\MyPath\v5.0\MyAssembly.dll"
else null),
fun assem name ignr ->
if assem = null then
Type.GetType(name, false, ignr)
else
assem.GetType(name, false, ignr))
不會針對字典類型和字串類型呼叫assemblyResolver 方法,因為這些類型名稱不是包含組件的限定名稱。
現在假設第一個泛型參數類型是 System.String,而不是 YourType,它是從 YourAssembly:
"System.Collections.Generic.Dictionary`2[[YourNamespace.YourType, YourAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null], [MyNamespace.MyType, MyAssembly]]"
因為這個元件既不是 mscorlib.dll/System.Private.CoreLib.dll 也不是目前正在執行的元件,所以您無法在沒有元件限定名稱的情況下解析 YourType 。 因為會以遞歸方式呼叫您的 assemblyResolve ,所以必須能夠處理此案例。 現在,它會使用提供的 null 物件執行元件載入,而不是對於MyAssembly以外的元件傳回 AssemblyName。
Type t2 = Type.GetType(test,
(aName) => aName.Name == "MyAssembly" ?
Assembly.LoadFrom(@".\MyPath\v5.0\MyAssembly.dll") :
Assembly.Load(aName),
(assem, name, ignore) => assem == null ?
Type.GetType(name, false, ignore) :
assem.GetType(name, false, ignore), true
);
let t2 =
Type.GetType(test,
(fun aName ->
if aName.Name = "MyAssembly" then
Assembly.LoadFrom @".\MyPath\v5.0\MyAssembly.dll"
else Assembly.Load aName),
(fun assem name ignr ->
if assem = null then
Type.GetType(name, false, ignr)
else
assem.GetType(name, false, ignr)), true)
解析包含特殊字元的類型名稱
某些字元在元件限定名稱中具有特殊意義。 如果簡單類型名稱包含這些字元,當簡單名稱是元件限定名稱的一部分時,字元會造成剖析錯誤。 若要避免剖析錯誤,您必須先使用反斜杠逸出特殊字元,才能將元件限定名稱傳遞至 GetType 方法。 例如,如果類型命名 Strange]Type為 ,則必須在方括弧前面加入逸出字元,如下所示: Strange\]Type。
備註
具有這類特殊字元的名稱無法在 Visual Basic 或 C# 中建立,但可以使用通用中繼語言 (CIL) 或發出動態元件來建立。
下表顯示類型名稱的特殊字元。
| 角色 | 意義 |
|---|---|
, (逗號) |
元件限定名稱的分隔符。 |
[] (方括弧) |
做為後綴組,表示陣列類型;以分隔符組的形式括住泛型自變數清單和元件限定名稱。 |
& (和號) |
做為後綴,表示類型是參考型別。 |
* (星號) |
用作後綴,用來表示類型是指標類型。 |
+ (加) |
巢狀類型的界限符號。 |
\ (反斜杠) |
逸出字元。 |
屬性,例如 AssemblyQualifiedName 傳回正確逸出字串。 您必須將正確逸出字串傳遞至 GetType 方法。 接著,方法會將 GetType 正確逸出的名稱 typeResolver 傳遞給 默認類型解析方法, 如果您需要將名稱與typeResolver中的未逸出名稱進行比較,則必須移除逸出字元。
混合名稱解析
下表摘要說明 中所有類型名稱和元件名稱assemblyResolver組合的、 typeResolver和 預設名稱解析之間的typeName互動:
| 類型名稱的內容 | 組件解析器方法 | 類型解析器方法 | 結果 |
|---|---|---|---|
| 類型、組裝 | 零 | 零 | 相當於呼叫 Type.GetType(String, Boolean, Boolean) 方法多載。 |
| 類型、組裝 | 提供 | 零 |
assemblyResolver 會傳回元件,如果無法解析元件,則傳回 null 。 如果元件已解析,則會使用 Assembly.GetType(String, Boolean, Boolean) 方法多載從該元件載入類型;否則,不會嘗試解析類型。 |
| 類型、組裝 | 零 | 提供 | 相當於將元件名稱 AssemblyName 轉換成 物件,並呼叫 Assembly.Load(AssemblyName) 方法多載以取得元件。 如果已解析元件,則會傳遞至 typeResolver,否則 typeResolver 不會呼叫 ,而且不會再嘗試解析類型。 |
| 類型、組裝 | 提供 | 提供 |
assemblyResolver 會傳回元件,如果無法解析元件,則傳回 null 。 如果已解析元件,則會傳遞至 typeResolver,否則 typeResolver 不會呼叫 ,而且不會再嘗試解析類型。 |
| 類型 | 無,提供 | 零 | 相當於呼叫 Type.GetType(String, Boolean, Boolean) 方法多載。 因為未提供元件名稱,因此只會搜尋 mscorlib.dll/System.Private.CoreLib.dll 和目前正在執行的元件。 如果提供assemblyResolver,則會忽略它。 |
| 類型 | 無,提供 | 提供 |
typeResolver 已被呼叫,並將 null 傳遞給組件。
typeResolver 可以從任何元件提供類型,包括它為了目的載入的元件。 如果提供assemblyResolver,則會忽略它。 |
| 集會 | 無,提供 | 無,提供 | FileLoadException擲回 ,因為元件名稱會剖析為元件限定型別名稱。 這會導致元件名稱無效。 |