Використання провайдерів компіляції в Asp.net, Різне, Програмування, статті

В Asp.net будь-яка інтернет-сторінка представляється у вигляді двох файлів: *. aspx і *. aspx.cs. В *. Aspx-файлах міститься html-подібна розмітка самої сторінки, а в *. Aspx.cs-файлах код на мові C #, який представлений у вигляді окремого класу. В розмітку сторінки можна додавати серверні елементи управління, наприклад тегом .


Причому з кожним таким оголошенням буде пов’язана змінна, тобто в нашому випадку ми отримаємо доступ до змінної типу Button і ім’ям MyButton, хоча на перший погляд ця змінна ніде не оголошена. (Хоча в першій версії Asp.net оголошення змінних вставлялися в той же файл.)

Насправді це не так. Клас, описаний в *. Aspx.cs-файлі є частковим (він позначений модифікатором partial), одна його частина описана в *. Aspx.cs-файлі, а друга знаходиться в тимчасовому файлі, який генерується на підставі перегляду *. aspx-файла. Генерацією цього тимчасового файлу якраз і займається провайдер компіляції.

Пишемо провайдер компіляції


1. Визначимося, що буде робити провайдер компіляції.

Щоб особливо не мудрувати, нехай він виконує перетворення xml-файла види:

 



  1. <classes>


  2.       <property type=”int” name=”x1″ value=”17″ />

  3.       <property type=”string” name=”x2″ value=”Hello, World!” />

  4.    </class>


  5.       <property type=”int” name=”x1″ value=”-5″ />


  6.    </class>

  7. </classes>
* This source code was highlighted with Source Code Highlighter.

в статичний клас, що містить константи.

2. Створимо новий проект. В якості типу проекту виберемо “Class Library”, назвемо його “MyLib”.

3. Всі провайдери компіляції є похідними від класу “System.Web.Compilation.BuildProvider”, поетом додамо посилання на збірку “System.Web” і використовуються простору імен.

Конструктор класу нічого не виконує, а ось метод “GenerateCode” нам потрібно перевизначити. У результаті повинно вийти наступне:

 



  1. using System;

  2. using System.Web.Compilation;

  3. using System.Xml;

  4. using System.IO;

  5. using System.Web.Hosting;

  6.  

  7. namespace MyLib

  8. {

  9.   public class MyBP: BuildProvider

  10.   {

  11.     public MyBP() { }

  12.  

  13.     public override void GenerateCode(AssemblyBuilder assemblyBuilder)

  14.     {

  15. / / В змінну writer будемо записувати генерований код

  16.       using (TextWriter writer = assemblyBuilder.CreateCodeFile(this))

  17.       {

  18. / / Створюємо xml-документ використовуючи шлях до аналізованого файлу

  19.         XmlDocument xml = new XmlDocument();

  20.         xml.Load(VirtualPathProvider.OpenFile(base.VirtualPath));

  21.  

  22. / / Отримуємо всі класи

  23.         XmlNodeList classes = xml.GetElementsByTagName(“class”);

  24.         foreach (XmlNode _class in classes)

  25.         {

  26. / / Отримуємо назва класу

  27.           string cName = _class.Attributes[“name”].Value;

  28.           if (cName == null // cName.Length == 0) continue;

  29.  

  30. / / Отримуємо поля класу

  31.           string cProperties = “”;

  32.  

  33. / / Отримуємо всі поля

  34.           XmlNodeList properties = _class.ChildNodes;

  35.           foreach (XmlNode property in properties)

  36.           {

  37.             if (property.Name != “property”) continue;

  38.  

  39. / / Отримуємо тип поля

  40.             string pType = property.Attributes[“type”].Value;

  41.             if (pType == null // pType.Length == 0) continue;

  42.  

  43. / / Отримуємо назву поля

  44.             string pName = property.Attributes[“name”].Value;

  45.             if (pName == null // pName.Length == 0) continue;

  46.  

  47. / / Отримуємо значення поля

  48.             string pValue = property.Attributes[“value”].Value;

  49.             if (pValue == null // pValue.Length == 0) continue;

  50.  

  51. / / Якщо поле має рядковий тип, беремо його в лапки

  52.             if (pType == “string”) pValue = string.Format(“”{0}””, pValue);

  53.  

  54. / / Додаємо поле

  55.             cProperties += string.Format(” public const {0} {1} = {2}; “, pType, pName, pValue);

  56.           }

  57.  

  58. / / Додаємо клас

  59.           writer.Write(” public static partial class ” + cName + ” { ” + cProperties + ” } “);

  60.         }

  61.       }

  62.     }

  63.   }

  64. }
* This source code was highlighted with Source Code Highlighter.

Компілюємо і отримуємо збірку.

4. Створюємо новий сайт (Назвемо його MySite). Перше, що потрібно зробити, створити папки bin і App_Code. В папку bin скопіюємо щойно створену бібліотеку. Тепер потрібно підключити провайдер компіляції. Для цього йдемо в файл Web.config і в розділі compilation додаємо блок:

 



  1. <buildProviders>

  2.    <add type=”MyLib.MyBP, MyLib” extension=”.cc” />

  3. </buildProviders>
* This source code was highlighted with Source Code Highlighter.

Це визначення говорить, що для файлів з розширенням “cc” буде використаний провайдер компіляції MyLib.MyBP, який буде узятий з збірки MyLib “.

5. Створюємо файл “my.cc” в папці “App_Code” з xml-кодом, на зразок того, що наведений вище. Через деякий час (зазвичай секунд десять, коли файл обробиться) в будь-якому C #-коді можна буде використовувати класи “C1” і “C2” та їх константні поля. (Результати можна побачити на скріншотах)

6. Скріншоти:

Документ, опрацьований провайдером компіляції:

З’явилися класи “C1” і “C2”:

І їх поля:

 

Ну і як кінцівки


Безумовно даний приклад не може претендувати на повноцінний провайдер компіляції, а показує тільки загальну ідею, в коді я опустив багато перевірки, обробку винятків пожертвував оптимальністю заради скорочення коду.

PS: Я не знайшов способу не поміщати провайдер в окрему збірку, а просто додати клас в папку App_Code. В даному випадку виникає помилка про неможливість завантажити тип.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*