Всяко асембли, независимо дали е статично или динамично, съдържа в себе си метаданни (информация, която го описва).
Метаданните включват описание на съдържаните в асемблито типове и информация за него самото.
Манифест на асембли
Информацията за асемблито описва как са свързани съдържаните елементи помежду си – това е т. нар. манифест. Манифестът съдържа всички метаданни, нужни за описанието на идентичността на асемблито, информация за неговата версия, необходимите му права, асемблитата и версиите им, нужни за изпълнението му, както и допълнителна информация, необходима за извличането на типовете и ресурсите.
Манифестът може да се съдържа в самото асембли (в неговия .exe или .dll преносим изпълним файл) заедно с останалите ресурси или като самостоятелен файл, който съдържа само информацията на манифеста.
Следващата илюстрация показва различните начини, по които се съхранява манифеста в асемблитата:
При асемблита, които съдържат един файл, манифестът е вмъкнат в PE файла и образува асембли от един файл. Възможно е създаването на многомодулно асембли с външен манифест или манифестът може да е вмъкнат в един от файловете.
Съдържание на манифеста
Следната таблица показва съдържанието на манифеста:
Информация
|
Описание
|
Идентификация
|
Име
|
Текст, указващ име на асембли.
|
Версия
|
Съдържа 4 идентификатора разделени с точка във формат: Major.Minor.Build.Revision (напр. 3.44.1234.5543).
|
Култура
|
RFC1766 низ, указващ регионални настройки (locale) на асемблито – например “en-US”. Тази информация трябва да се използва, когато се създава сателитно асембли, съдържащо специфична културна и езикова информация. Възможно е асемблито да е с неутрална култура. (Асемблита с информация за културата автоматично се възприемат като сателитни).
|
Информация за силно именуване
|
Съдържа публичния ключ, използван за цифровия подпис на асемблито, ако то притежава силно име.
|
Списък на файловете, включени в асемблито
|
Хеш стойност и име на файл, включен в асемблито. Забележка: Всички файлове трябва да са в папката, където се намира е файлът, съдържащ манифеста.
|
Съдържани типове
|
Тази информация се използва по време на изпълнение за зареждане на типовете декларирани в асемблито.
|
Външни асемблита
|
Списък с всички външни асемблита, които са статично свързани. Всяко свързано асембли е описано с име и метаданни (версия, култура, и т.н.) и публичен ключ, ако е силно именувано.
|
Изисквани права за достъп
|
Необходими права, за да се изпълни асемблито.
|
Първите четири елемента (име, версия, култура, публичен ключ) образуват идентификацията на асембли – неговото силно име.
Атрибути за работа с манифест
В .NET Framework има няколко атрибута, чрез които можем да влияем на компилацията на асемблитата и да променяме метаданните в техния манифест. Тези атрибути се записват в сорс кода на асемблито и при компилация модифицират метаданните. Ето по-важните от тях:
Атрибут на манифеста
|
Описание
|
AssemblyCultureAttribute
|
RFC1766 низ указващ към коя култура принадлежат ресурсите, съдържани от асемблито. Формата е "език"-"страна или регион" – например "en-US" за US English или "bg-BG" за ресурси на български език. Културата може да бъде също неутрална, което показва, че асемблито съдържа ресурси за културата по подразбиране.
Забележка: CLR третира всяко асембли с този атрибут за сателитно.
|
AssemblyFlagsAttribute
|
Указва дали асемблито поддържа едновременно различни версии в един компютър, в един процес или в един домейн на приложение (т. нар. side-by-side изпълнение, което ще разгледаме по-подробно в секцията за Global Assembly Cache).
|
AssemblyVersionAttribute
|
Съдържа 4 идентификатора разделени с точка: Major.Minor.Build.Revision (напр. 3.44.1234.5543).
|
AssemblyCompanyAttribute
|
Текстов низ, указващ име на компанията, производител на асемблито.
|
AssemblyCopyrightAttribute
|
Текстов низ, описващ авторски права.
|
AssemblyFileVersionAttribute
|
Текстов низ, указващ Win32 файлова версия. По подразбиране това е версията на асемблито.
|
AssemblyInformationalVersionAttribute
|
Текстов низ, указващ версия, която не се използва от CLR. Това може да бъде версия на продукт или друга, която носи информация за разработчиците.
|
AssemblyProductAttribute
|
Текстов низ, указващ име на софтуерен продукт.
|
AssemblyTrademarkAttribute
|
Текстов низ, указващ търговска марка.
|
AssemblyConfigurationAttribute
|
Текстов низ, указващ конфигурация на асемблито (Release или Debug). CLR не използва този атрибут.
|
AssemblyDefaultAliasAttribute
|
Текстов низ, указващ псевдоним по подразбиране, който ще се използва при свързване от външни асемблита. Може да бъде лесно за използване име (докато името на асемблито може да не е). Може да е също съкратена форма на пълното име на асемблито.
|
AssemblyDescriptionAttribute
|
Текстов низ, съдържащ кратко описание на съдържанието и целта на асемблито.
|
AssemblyTitleAttribute
|
Текстов низ, указващ лесно име на асемблито (напр. Microsoft Common Dialog Control).
| Атрибути за работа с манифест – пример
Ето един пример, в който чрез атрибути се задават метаданни за асемблито:
AssemblyInfo.cs
|
using System.Reflection;
[assembly: AssemblyTitle("Advanced Toolbar Control")]
[assembly: AssemblyDescription(
"Advanced Toolbar Windows Forms Control")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCompany("Software Abuse Corp.")]
[assembly: AssemblyProduct(
"Software Abuse Windows Controls Library")]
[assembly: AssemblyCopyright(
"(c) 2005 by Software Abuse Corp.")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("3.22.*")]
|
Във VS.NET метаданните за асемблито обикновено се записват във файла AssemblyInfo.cs, който се създава автоматично с всеки нов проект. В примера сме използвали този файл, за да дефинираме метаданни за асемблито, до което се компилира текущия проект – контролата "Advanced Toolbar Control".
Създаване на многомодулно асембли
Тъй като VS.NET не може да създава многомодулни асемблита, ако се наложи да използваме такива, можем да ги създадем от командния ред чрез подходящи извиквания на C# компилатора (csc.exe). Да разгледаме стъпките, чрез които можем да създадем асембли, което се състои от няколко файла.
Стъпка 1: Компилиране на модул, който ще бъде използван от други асемблита
Нека имаме файл Utilities.cs със следното съдържание:
Utilities.cs
|
// Assembly building in the .NET Framework – example
using System;
namespace Utilities
{
public class ConsoleFunctions
{
public void ConsoleWrite()
{
System.Console.WriteLine("A line from Utilities!");
}
}
}
|
Компилираме го с командата:
csc /target:module Utilities.cs
|
След успешното компилиране е създаден файл Utilities.netmodule в същата папка.
Стъпка 2: Компилиране на асембли, което използва вече създадения модул
Създаваме файл Client.cs в същата папка:
Client.cs
|
using System;
using Utilities; // The namespace created in Utilities.netmodule
class MainClientApp
{
// Static method Main is the entry point method.
public static void Main()
{
ConsoleFunctions myFunctions = new ConsoleFunctions();
Console.WriteLine("Client code executes");
// Call function from module Utilities.netmodule
myFunctions.ConsoleWrite();
}
}
|
Можем да го компилираме с командата:
csc Client.cs /addmodule:Utilities.netmodule
|
Този път компилаторът създава файла Client.exe.
|
За да се зареди асемблито трябва да са налични всички модули. Това е се налага от факта, че асемблито се компилира от IL код до машиннозависим код от JIT компилатора.
| Разглеждане на манифеста на асембли с ildasm
Вече се запознахме какво представляват манифестите на асемблитата и как можем да променяме метаданните, които се записват в тях при компилация. Нека сега видим как можем да разгледаме манифеста на съществуващо асембли.
MSIL Disassembler (ildasm.exe) е придружаващ инструмент към MSIL Assembler (ilasm.exe). С този инструмент може да се разглежда съдържанието на асемблитата и модулите. MSIL Disassembler e част от .NET Framework SDK и се намира по подразбиране в директорията
%Program Files%\Microsoft Visual Studio .NET 2003\SDK\v1.1\bin.
За да разгледаме метаданните и манифеста на асемблито Client.exe, получено в горния пример, ще го отворим с MSIL Disassembler чрез следния команден ред:
Двойно щракване с левия бутон на мишката върху “M A N I F E S T” ще отвори прозорец със съдържанието на манифеста:
Както се вижда, манифестът дефинира асемблито Client, което съдържа модула Client.exe и реферира външния модул Utilities.netmodule от файла Utilities.netmodule, както и външното асембли mscorlib и външния клас Utilities.ConsoleFunctions.
Повече информация относно MSIL Disassembler можете да намерите в MSDN – http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cptools/html/cpconMSILDisassemblerIldasmexe.asp.
Силно именуване на асембли
С цел повишаване на сигурността и намаляване на конфликтите с версиите в .NET Framework са въведени т. нар. силно именувани асемблита. Силното име на асембли се образува от неговите име, версия, култура и публичен ключ. Всяко силно именувано асембли е цифрово подписано с частния ключ, съответстващ на публичния ключ, който участва в силното му име. Пример за силно име на асембли е следният низ:
CompanyNamespace.Controls.Design.v3.2,Version=3.2.111251.37,Culture=neutral, PublicKeyToken=8ty5c3176f5cd04e
|
Силно именуваните асемблита имат някои предимства пред обикновените асемблита:
-
Гарантира се уникалността, с помощта на двойка ключове (public / private key pair). Никой не може да създаде асембли със същото име, без да притежава частния ключ. Асембли, създадено с един частен ключ, се различава от асембли, създадено с друг частен ключ.
-
Защитава родословието на версиите. Нова версия, която е създадена без притежаването на същия частен ключ като предходната, лесно може да бъде идентифицирана.
-
Защитава се целостта на асемблито и дадените му права (permissions). По този начин се гарантира, че подмяна на асембли, с цел използване на неговите права (permissions) e невъзможно.
Само силно именувани асемблита може да се добавят в областта Global Assembly Cache, която ще дискутираме след малко.
Създаване на силно именувано асембли – пример
В следващия пример ще създадем силно именувано асембли и ще покажем особеностите в неговия манифест.
Първо ще създадем двойка публичен / частен ключ (public/private key pair). За целта използваме Strong Name инструмента (sn.exe), който е част от .NET Framework SDK:
Тази команда генерира по случаен начин двойка публичен/частен ключ и ги записва във файла keypair.snk.
След като вече имаме двойката ключове, можем да пристъпим към създаване на силно именувано асембли:
-
Стартираме Visual Studio .NET 2003.
-
Създаваме нов проект от тип Class Library: File -> New -> Project -> Visual C# Projects -> Class Library. Задаваме име на проекта MyStrongNamedAssmbly и потвърждаваме с бутона [OK].
-
Компилираме проекта. Създадохме обикновено асембли (то се намира в поддиректорията bin\Debug\ на проекта, във файла MyStrongNamedAssembly.dll). Неговият манифест изглежда по следния начин:
-
Копираме създадения по-горе файл keypair.snk в папката, която съдържа VS.NET проекта (MyStrongNamedAssembly.csproj).
-
От Solution Explorer отваряме файла AssemblyInfo.cs и намираме реда [assembly: AssemblyKeyFile("")]. Това е атрибутът, който ще използваме, за да посочим двойката публичен/частен ключ. Конструкторът на AssemblyKeyFileAttribute приема като параметър име на файл, съдържащ двойката ключове. Може да бъде твърд път (c:\keyfiles\keypair.snk) или относителен път спрямо obj\Debug поддиректорията на проекта. В нашия случай можем да зададем относителен път: ..\..\keypair.snk.
-
Променяме атрибута AssemblyKeyFileAttribute на [assembly: AssemblyKeyFile(@"..\..\keypair.snk")]:
-
Компилираме проекта отново. Сега вече създадохме силно именувано асембли (то се намира отново в поддиректорията bin\Debug\ на проекта, във файла MyStrongNamedAssembly.dll). Неговият манифест се различава от предходния по .publickey частта:
Сподели с приятели: |