Vítejte na blog.vyvojar.cz Přihlásit | Registrovat | Pomoc
Titulní Blogy Fotky Soubory

2P.Knowledge.Blog.API

Jak "zkamarádit" assembly

Objektově orientovaný přístup nám definuje několik modifikátorů viditelnosti typů či jejich členů (public, protected, private). V jazyku C# existuje jeden specifický modifikátor přístupu, který je na rozdíl od dříve zmíňených vázaný na konkrétní umístění kódu typu. Nemám na mysli nic jiného, než specifikátor přístupu internal, který daný typ či člen učiní viditelný pouze pro typy v rámci assembly, ve které je definován.

Od .NET frameworku verze 2.0 existuje způsob, který nám umožní na úrovni assembly definovat, že některé vybrané assembly budou mít přístup k interním typům či členům, označených specifikátorem přístupu internal. K takovémuto rozhodnutí můžou být různé důvody - zviditelnění nějakého API vybraným částem aplikace, unit testy atd. Tento způsob je představován použitím speciálního atributu InternalsVisibleTo.

Pojďme se podívat na jednoduchý příklad použití.

Mějme dvě assembly - LibraryA a LibraryB.
Na úrovni assembly s názvem LibraryB je definován interní typ obsahující interní člen.

namespace LibraryB
{
  internal class ClassFromLibraryB
  {
    internal void SomeMethod()
    { 
      //implementace metody..
    }
  }
}

Pokud bychom tento typ a jeho metodu chtěli použít z typu, který je obsažen v assembly s názvem LibraryA, tak by kompilace našeho projektu zcela logicky skončila chybou (LibraryB.ClassFromLibraryB' is inaccessible due to its protection level). Pokud ovšem na úrovni assmbly LibraryB aplikujeme atribut InternalsVisibleTo, kompilace po této změně proběhne bez problémů, protože jsme tímto assembly LibraryA prohlásili za assembly přátelskou (Friendly assembly).

//assembly s nazvem LibraryA oznacime za pratelskou
[
assembly: System.Runtime.CompilerServices.InternalsVisibleTo("LibraryA")]
namespace LibraryB
{
  internal class ClassFromLibraryB
  {
    ...
  }
}

Níže uvedený kód již tedy bude zkompilovatelný.

/// <summary>
/// Trida, ktera vyuziva sluzeb internich typu z assembly LibraryB.
/// </summary>
public class ClassFromLibraryA
{
  public void DoSomething()
  {
  //je mozne vytvorit instanci interniho typu pratelske assembly
  ClassFromLibraryB friendlyType = new ClassFromLibraryB();
  //je mozne zavolat interni metodu na typu z pratelske assembly
  friendlyType.SomeMethod();
  }
}

Pokud by assembly s názvem LibraryA měla silné jméno, situace se nám trochu zkomplikuje, protože v takovémto případě je nutné při použití atributu InternalsVisibleTo specifikovat kromě názvu assembly i hodnotu veřejného klíče (pozor, opravdu ne token veřejného klíče, jak by někteří mohli očekávat). Hodnotu veřejného klíče z podepsané assembly je možné získat pomocí utility sn.exe například s přepínačem -Tp. V kontextu našeho příkladu by tedy použití atributu InternalsVisibleTo vypadalo nějak takto (veřejný klíč není z důvodu jeho délky uveden celý):

[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("LibraryA, PublicKey=0024000004 ... 4dd65a3085dd5")]

Samozřejmě je dobré této vlastnosti používat z rozmyslem a pouze v opodstatněných a dobře promyšlených případech.

P.S. I přesto, že jsem v .NET "čístý" C#ista, zmíním, že pro přátelské assembly je nyní s příchodem .NET 3.5 podpora už i v novém Visual Basicu 9. Viz tento link.

Zveřejněno 1. prosince 2007 22:41 by Puschak
Vedeno pod:

Komentář

Žádné komentáře
Neregistrovaní uživatele nemužou přidávat komentáře.
Powered by Community Server (Personal Edition), by Telligent Systems
Vyvojar.cz na prodej!