Friend 組件 (C++)
對於適用的運行時間, friend 元件 語言功能會讓元件元件中的類型位於命名空間範圍或全域範圍,可供一或多個用戶端元件或 .netmodules 存取。
所有執行階段
備註
(不是所有執行階段都有支援這個語言功能)。
Windows 執行階段
備註
(Windows 執行階段不支援這個語言功能。)
需求
編譯器選項: /ZW
通用語言執行平台
備註
讓組件元件中在命名空間範圍或全域範圍的類型可存取用戶端組件或 .netmodule
在元件中,指定組件屬性 InternalsVisibleToAttribute,並傳遞將存取元件中在命名空間範圍或全域範圍之類型的用戶端組件或 .netmodule 的名稱。 您可以藉由指定其他屬性來指定多個用戶端組件或 .netmodule。
在用戶端組件或 .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");
}
};
下列程式碼範例會定義嘗試存取元件中私用類型 (其未將存取權授與其私用類型) 的用戶端。 由於執行階段的行為,如果您要攔截例外狀況,您必須嘗試存取在 helper 函式的私用類型。
// 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