Динамічне завантаження збірки в Visual C # (Sharp)

У термінах NET, щоб використовувати конфігураційний файл з динамічно зружаемим додатком, необхідно завантажити збірку і з збірки створити еемпляр типу До посиланнях можна звертатися локально або з кеша GAC

Код для динамічного створення екземпляра типу вимагає розбиття розділеної запитом рядка на що містяться в ній окремі ідентифікатори Для органованності процесу ці три елементи зберігаються в класі Цей клас можна НВАТ класом даних, тому що він містить тільки члени даних

Клас даних є заповнювачем, який потрібно тільки для коду, примяти для динамічного завантаження типу Це дозволяє визначити клас даних приватним, т к приватний клас увазі, що тільки батьківський клас може створювати його екземпляри

Визначивши клас configurationLoader як клас для динамічного створення еемпляров інших типів, оголошуємо приватний клас таким чином (додаємо в збірку Definitions):

namespace Definitions

{

public class ConfigurationLoader { private class Configyrationlnfo {

public string AssemblyName public string TypeName,- public string EasyName

}

Dictionary&ltstring, ConfigurationInfo&gt _availableTypes

}

}

Клас Configurationlnfo містить три члена даних: AssemblyName, TypeName і EasyName З класом застосовується модифікатор private, який вказує, що ніщо поза класом conf igurationLoader не може створити екземпляр конфігурації Якби клас Configurationinfo був оголошений з модифікатором public, то слующій код був би легітимним:

ConfigurationLoaderConfigurationinfo els = new ConfigurationLoaderConfigurationinfo)

Клас Configurationinfo застосовується для зберігання інформації, отриманої з конфігураційного файлу Елементи конфігураційної інформації повязані між собою перехресними посиланнями з допомогою типу Dictionary, ключем у кором служить член даних EasyName

Для аналізу конфігураційної інформації і створення окремих екземплярів Configurationinfo застосовується наступний код (що є частиною Configur-tionLoader):

public void Load() {

string value = ConfigurationManagerAppSettings[&quotassemblies&quot] string[] values = valueSplit(/)

for (int cl =0 cl &lt valuesLength cl += 3) {

_availableTypesAdd( values cl],

new Configurationinfo { EasyName = values[cl],

TypeName = values[cl + 1], AssemblyName = values[cl + 2] })

}

}

Конфігурація зчитується с допомогою AppSettings, після чого перетворюється в масив строкових елементів Елементи масиву обробляються в циклі по три елементи за раз З кожною итерацией циклу створюється екземпляр configurationinfo Після обробки конфігураційної рядки, можна дініческі створювати екземпляр типу за допомогою методу instantiate класу ConfigurationLoader:

using SystemReflection

public RequestedType Instantiate&ltRequestedType&gt(string identifier) {

if (_availableTypesContainsKey(identifier)) { Configurationlnfo info = _availableTypes[identifier] AssemblyName assemblyName =

AssemblyNameGetAssemblyName(infoAssemblyName)

Assembly assembly = AssemblyLoad(assemblyName)

object obj = assemblyCreatelnstance(infoTypeName)

return (RequestedType)obj

}

else {

throw new ArgumentException(&quotidentifier (&quot +

identifier + &quot) is not a listed type&quot)

}

}

Подивившись на оголошення методу instantiate о, можна побачити, що він є методом узагальнення NET, які розглядаються в главі 11 Метою є створити екземпляр типу та виконати автоматичне перетворення в запрошеий тип Таким чином, немає потреби визначати метод instantiate () з помью типу object Параметр identifier є рядком, яка використовується для пошуку ідентифікатора в члені даних _availabieTypes колекції Dictionary Якщо _avaiiabieTypes містить ідентифікатор, то витягується еемпляр configurationlnfo, за допомогою якого створюється екземпляр даного та За відсутності примірника видається виняток

Фрагмент коду був виділений жирним шрифтом, бо подібного коду ми ще не розглядали У цих трьох рядках коду демонструється вбудована в NET можливість динамічного виконання коду У першій виділеної жирним шрифтом рядку коду дозволяється можливість відображення, а в другій загружаея складання Так, наприклад, якби параметр identifier був impii, то перша жіая строчка коду посилалася б на збірку Implementationsldll і динамічно Загрей б цю збірку Але тут мається заковика, яка полягає в тому, що збірку Implementationsldll можна завантажити динамічно, тільки якщо вона є в лальнейшем папці або в кеші GAC Як альтернативне рішення можна було б вказати повний шлях у визначенні збірки Але дана стратегія має недосток, що полягає в тому, що збірка завжди повинна знаходитися в одному і тому ж місці на різних компютерах

Коли друга жирна рядок коду присвоює значення змінної збірки assembly, то цієї збіркою є завантажена складання NET Збірка буде проанізірована, після чого можна буде створити екземпляр типу У третій виділеної жирним рядку коду викликається метод Createisntanceo, якому в параметрах передається імя типу, примірник якого потрібно створити, що включає простратво імен Таким чином, наприклад, якщо завантажена збірка Implementationsldll,

то можна буде створити екземпляр типу implementation. implementation Створення примірника буде успішним, незважаючи на ТО, що Implementationsl Implementation є приватним класом, т к ми застосовуємо принципи динамічного програірованія

Але створення екземпляра типу не означає, що цей екземпляр можна використовувати Для цього необхідно виконати приведення типу до типу, який був оголошений загальним (public)

Ми будемо продовжувати розглядати приклад Implementations Implementation, намагаючись вирахувати, як створити його екземпляр і маніпулювати цим примірниках Але перш ніж займатися цим кодом, нам необхідно розглянути ще одну можливість програмування: Синглетон (singletons)

Використання Синглетон

Так як клас ConfigurationManager є статичним, то з нього не можна створити екземпляри Статичний клас зі своїми статичними методами і стическими членами даних є класом одноцільового призначення Такий же ефект можна отримати, створивши Синглетон (singleton) Синглетон подібний статічкому класу, тільки з нього можна створювати екземпляри Перевага сінглонов в тому, що можна створювати множинні Синглетон одного типу при нічіі одного статичного класу

Статичний клас можна порівняти з єдиним ключем до замку Якщо це зок на особистому сейфі, то, швидше за все, ви не захочете, щоб до нього було неяк ключів у різних людей Але що якщо це замок від вхідних дверей вашого будинку або квартири Якщо тільки ви не холостяк, то тоді до замку буде кілька клей, але не у всякого, а тільки у членів вашої родини Ситуацію з ключем до сейфа можна порівняти зі статичним класом, а з ключами до сімейного дому – з сінетоном Можна сперечатися, що для сейфа можна також застосувати Синглетон, але тільки одну його копію Але такий аргумент не бере до уваги те обстоельство, що за допомогою належним чином написаного вихідного коду можна створити і другий, і третій і т д примірник Синглетон А створити інший екземяр статичного класу неможливо, що забезпечує певний стиль прраммірованія

Визначимо клас ConfigurationLoader як Синглетон Це передбачає слідуючи дві обставини:

• створення властивості instance, що посилається на одиничний екземпляр класу

ConfigurationLoader

• визначення класу ConfigurationLoader як private, що має на увазі, що тільки він сам може створювати свої екземпляри Таким чином, обеспечіваея поведінку класу ConfigurationLoader подібне поведінки статичного класу в тому сенсі, що його клієнт не зможе створювати екземпляри даного класу

Далі наводиться КОД Синглетон ConfigurationLoader (знаходиться в збірці

Definitions):

static ConfigurationLoader „instance static ConfigurationLoader() {

„instance = new ConfigurationLoader()

&gt&nbsp

ConfigurationLoader) {

„availableTypes = new Dictionary&ltstring, ConfigurationInfo&gt()

}

public static ConfigurationLoader Instance { get {

return „instance

}

}

Властивість Синглетон instance оголошено static, що дозволяє звернення до ConfigurationLoader instance Реалізація статичного властивості повинна Ссать на статичний член даних, яким у даному прикладі є член даих instance Примірник члена даних instance створюється статичним консуктором static ConfigurationLoaderо Конструктор примірника створить екземпляр availableTypes типу Dictionary Зверніть увагу на відсутність модифікатора public в оголошенні, що має на увазі приватну область видимості

Використання створеного екземпляра

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

ConfigurationLoaderInstanceLoad() IDefinition definition =

ConfigurationLoaderInstanceInstantiate&ltIDefinition&gt(&quotImpll&quot)

ConsoleWriteLine(definitionTranslateiWord(&quothello&quot))

ПРИМІТКА

Може статися, що при виконанні цього коду зявляться помилки Якщо у вас возніут такі труднощі, то це тому, що збірки не знаходяться в одному каталозі і моди динамічної й завантаження не можуть знайти їх Проблема вирішується приміщення м всіх збірок в один общи ї каталог

У першій рядку коду з конфігураційного файлу витягується інформація про збірці і типі У другій сходинці створюється екземпляр impii, після чого випояется приведення ImplementationsiImplementation До типу IDefinition Преденіе буде успішним, тому що інтерфейс IDefinition був реалізований

З ДОПОМОГОЮ ImplementationsiImplementation Мінлива definition буде посилатися на дійсний екземпляр обєкта, який реалізує iDefinition і модTranslateWord()

Тут нам потрібно зупинитися і подумати над тим, що сталося Ми визначили в конфігураційному файлі місцезнаходження типу Вихідний код в додатку прочитав конфігураційний файл під час виконання і зберіг наявні типи Викликає код знав тільки про абстрактне типі impii і те, що він реальний інтерфейс iDefinition Потім за допомогою динамічних методів NET була завантажена збірка типу та створено його примірник Даний процес унікальний в тому, що надає адміністратору можливість модифікування інформації про тип, чий екземпляр необхідно створити, і про його місцезнаходження, чи не вимагаючи при цьому рекомпіляції або оновлення інфраструктури Така гнучкість значно спрощує оновлення функціональності, не вимагаючи при цьому поновлення клієнта функціональності

ПРИМІТКА

Користь з можливості динамічного оновлення функціональності витягує тільки адміністратор програми Розробнику ж така можливість предостаяет мінімальну вигоду, т к він вже перетворив архітектуру для використання компонентів Загалом, розробники розглядають цей підхід до використання компонентів як створення архітектури модулів

Джерело: Гросс К С # 2008: Пер з англ – СПб: БХВ-Петербург, 2009 – 576 е: ил – (Самовчитель)

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


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

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

Ваш отзыв

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

*

*