In this example, the assembly makes internal types and internal members visible to the assembly called cs_friend_assemblies_2.
// cs_friend_assemblies.cs
// compile with: /target:library
using System.Runtime.CompilerServices;
using System;
[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]
// internal by default
class Class1
{
public void Test()
{
Console.WriteLine("Class1.Test");
}
}
// public type with internal member
public class Class2
{
internal void Test()
{
Console.WriteLine("Class2.Test");
}
} In this example, the assembly consumes internal types and internal members in assembly cs_friend_assemblies.dll.
Notice that you must explicitly specify the name of the output file (/out:cs_friend_assemblies_2.exe).
If this assembly gives another assembly (assembly C) access to its internal types and members, assembly C does not automatically become a friend of assembly cs_friend_assemblies.dll.
// cs_friend_assemblies_2.cs
// compile with: /reference:cs_friend_assemblies.dll /out:cs_friend_assemblies_2.exe
public class M
{
static void Main()
{
// access an internal type
Class1 a = new Class1();
a.Test();
Class2 b = new Class2();
// access an internal member of a public type
b.Test();
}
} Output
Class1.Test
Class2.Test
This example shows how to make internal types and members available for assemblies that have strong names.
To generate the keyfile and display public key, use the following sequence of sn.exe commands (for more information, see Strong Name Tool (Sn.exe)):
-
sn -k friend_assemblies.snk // Generate strong name key
-
sn -p friend_assemblies.snk key.publickey // Extract public key from key.snk into key.publickey
-
sn -tp key.publickey // Display public key stored in file'key.publickey
Pass the keyfile to the compiler with /keyfile.
// cs_friend_assemblies_3.cs
// compile with: /target:library /keyfile:friend_assemblies.snk
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("cs_friend_assemblies_4, PublicKey=0024000004800000940000000602000000240000525341310004000001000100031d7b6f3abc16c7de526fd67ec2926fe68ed2f9901afbc5f1b6b428bf6cd9086021a0b38b76bc340dc6ab27b65e4a593fa0e60689ac98dd71a12248ca025751d135df7b98c5f9d09172f7b62dabdd302b2a1ae688731ff3fc7a6ab9e8cf39fb73c60667e1b071ef7da5838dc009ae0119a9cbff2c581fc0f2d966b77114b2c4")]
class Class1
{
public void Test()
{
System.Console.WriteLine("Class1.Test");
}
} This example shows how to consume internal types and members available for assemblies that have strong names.
// cs_friend_assemblies_4.cs
// compile with: /keyfile:friend_assemblies.snk /reference:cs_friend_assemblies_3.dll /out:cs_friend_assemblies_4.exe
public class M
{
static void Main()
{
Class1 a = new Class1();
a.Test();
}
} Output
Class1.Test