對於適用的執行階段,友元組件語言功能允許組件中的類型位於命名空間範圍或全域範圍時,可供一個或多個用戶端組件或 .net 模組存取。
所有執行階段
備註
(不是所有執行階段都有支援這個語言功能)。
Windows 執行階段
備註
(Windows 執行階段不支援這個語言功能。)
需求
編譯器選項: /ZW
通用語言執行平台
備註
讓組件元件中在命名空間或全域範圍內的類型可供用戶端組件或 .netmodule 存取
在元件中,指定組件屬性 InternalsVisibleToAttribute,並傳遞將存取元件中在命名空間範圍或全域範圍之類型的用戶端組件或 .netmodule 的名稱。 您可以通過指定其他屬性來指定多個用戶端組件或 .netmodules。
在用戶端組件或 .netmodule 中,當您使用
#using參考元件組件時,請傳遞as_friend屬性。 如果您為組件指定的as_friend屬性並未指定InternalsVisibleToAttribute,如果您嘗試存取元件中在命名空間範圍或全域範圍的類型,將會擲回執行階段例外狀況。
如果包含 InternalsVisibleToAttribute 屬性的組件沒有強式名稱,而是使用 as_friend 屬性的用戶端組件卻有強式名稱,此時會發生建置錯誤。
雖然命名空間範圍和全域範圍的類型可以被用戶端組件或 .netmodule 識別,但成員的存取性仍然有效。 例如,您無法存取私人成員。
必須明確授與組件中所有類型的存取權。 例如,如果組件 C 參考組件 B,而組件 B 具有組件 A 中所有類型的存取權,則組件 C 沒有組件 A 中所有類型的存取權。
如需了解如何使用 Microsoft C++ 編譯器為元件授與強名稱(即簽署)的資訊,請參閱 強名稱元件(元件簽署)(C++/CLI)。
作為使用 friend 程式集功能的替代方案,您可以使用 StrongNameIdentityPermission 限制對單一類型的存取。
需求
編譯器選項: /clr
範例
下列程式碼範例定義一個元件,此元件指定一個用戶端組件可以存取該元件中的類型。
// friend_assemblies.cpp
// compile by using: /clr /LD
using namespace System::Runtime::CompilerServices;
using namespace System;
// an assembly attribute, not bound to a type
[assembly:InternalsVisibleTo("friend_assemblies_2")];
ref class Class1 {
public:
void Test_Public() {
Console::WriteLine("Class1::Test_Public");
}
};
下一個程式碼範例會存取元件中的私用類型。
// friend_assemblies_2.cpp
// compile by using: /clr
#using "friend_assemblies.dll" as_friend
int main() {
Class1 ^ a = gcnew Class1;
a->Test_Public();
}
Class1::Test_Public
下一個程式碼範例會定義元件,但不指定具有元件中各類型之存取權的用戶端組件。
請注意,元件是使用 /opt:noref 連結。 這可確保私有類型在元件的中繼資料中被發佈,而當 InternalsVisibleTo 屬性存在時,則不需要如此處理。 如需詳細資訊,請參閱 /OPT (優化) 。
// friend_assemblies_3.cpp
// compile by using: /clr /LD /link /opt:noref
using namespace System;
ref class Class1 {
public:
void Test_Public() {
Console::WriteLine("Class1::Test_Public");
}
};
下列程式碼範例定義了一個用戶端,該用戶端嘗試存取元件的私用類型,但元件不允許存取其私用類型。 由於執行時期的行為,如果您要捕捉例外,您必須嘗試存取輔助函式中的私用類型。
// friend_assemblies_4.cpp
// compile by using: /clr
#using "friend_assemblies_3.dll" as_friend
using namespace System;
void Test() {
Class1 ^ a = gcnew Class1;
}
int main() {
// to catch this kind of exception, use a helper function
try {
Test();
}
catch(MethodAccessException ^ e) {
Console::WriteLine("caught an exception");
}
}
caught an exception
下一個程式碼範例顯示如何建立可指定具有元件類型存取權之用戶端組件的強式名稱元件。
// friend_assemblies_5.cpp
// compile by using: /clr /LD /link /keyfile:friend_assemblies.snk
using namespace System::Runtime::CompilerServices;
using namespace System;
// an assembly attribute, not bound to a type
[assembly:InternalsVisibleTo("friend_assemblies_6, PublicKey=00240000048000009400000006020000002400005253413100040000010001000bf45d77fd991f3bff0ef51af48a12d35699e04616f27ba561195a69ebd3449c345389dc9603d65be8cd1987bc7ea48bdda35ac7d57d3d82c666b7fc1a5b79836d139ef0ac8c4e715434211660f481612771a9f7059b9b742c3d8af00e01716ed4b872e6f1be0e94863eb5745224f0deaba5b137624d7049b6f2d87fba639fc5")];
private ref class Class1 {
public:
void Test_Public() {
Console::WriteLine("Class1::Test_Public");
}
};
請注意,該元件必須指定其公開金鑰。 建議您依序在命令提示字元執行下列命令,以建立金鑰組,並取得公開金鑰:
sn -d friend_assemblies.snk
sn -k friend_assemblies.snk
sn -i friend_assemblies.snk friend_assemblies.snk
sn -pc friend_assemblies.snk key.publickey
sn -tp key.publickey
下一個程式碼範例會存取強式名稱元件中的私人類型。
// friend_assemblies_6.cpp
// compile by using: /clr /link /keyfile:friend_assemblies.snk
#using "friend_assemblies_5.dll" as_friend
int main() {
Class1 ^ a = gcnew Class1;
a->Test_Public();
}
Class1::Test_Public