Пишу клас, який відповідає за регулювання роботи налаштувань програми. Мені потрібно мати метод, який всім властивостям задасть значення за замовчуванням. Зайшов у глухий кут, щось не знаю, як добити питання. код:
Якщо використовувати дженерики, стикаюся з проблемою. Мені потрібно в аксессор get для поля можете отримувати значення з реєстру, пишу так:
return Convert.ToInt32 (res); - проблема - як вказати що потрібно повернути змінну типу T
І ще одна ремарка. Налаштування - це ім'я + значення, або ім'я + значення + дефолтний значення. Як на мене - ну ніяк не в'яжеться сюди ім'я + дефолтний значення + стартувати при запуску ОС. Щось не так спроектовано. Давайте ще раз. Є одна настройка, є набір налаштувань. Вони все string тільки чи можуть бути ще Int, bool і так далі? - A K 26 Березня о 12:46
@AK я хотів зробити по-розумному, щоб тип поля Value для примірника настройки визначався при створенні екземпляра. Чи не подужав цю тему і вирішив зробити Value просто типу string, а там вже приводити до чого треба. З налаштуванням "стартувати при запуску ОС" логіка залишається та ж, просто якщо ТАК - записуємо в реєстр потрібний рядок, якщо немає - стираємо - Antykus 26 Березня о 12:52
Давайте спочатку з'ясуємо, як це можна зробити технічно.
Для початку, як отримати список всіх полів? У нас є метод Type.GetFields (). але який наш тип? typeof (Options) може і не бути нашим справжнім типом, раптом ми зробили клас-нащадок? Правильний метод отримання типу - метод GetType ().
Далі, які поля ми хочемо отримати? Нам потрібні як відкриті (public. Так і закриті private) поля: зазвичай поля приховують, а відкривають властивості. Крім того, нам потрібні поля екземпляра, але не статичні поля. Але метод GetFields повертає лише відкриті поля для класів-предків, тому нам доведеться ітерованих по всіх базових типів.
Якщо ми вже ітеріруем за всіма типами, нам не потрібно отримувати успадковані поля, тому згодуємо в GetFields модифікатор BindingFlags.DeclaredOnly.
Це призводить до такого коду:
Що всередині циклу? Нам потрібно присвоїти значення за замовчуванням. Якщо це значення default (T) даного типу, то можна отримати його за допомогою наступного коду:
Це перевіряє, чи є наш типу значущим або посилальним типом. Для посилального типу default-значення є null. а значущий тип має конструктор за замовчуванням.
Якщо ж ви зберігаєте default-значення в одному з полів, і відрізняєте по імені, то незрозуміло, що робити, якщо тип поля і тип default-значення розрізняються. Для вашого випадку можна написати просто:
а якщо ви хочете уникнути присвоювання default-значення самого себе, то треба перевірити його ім'я і приналежність (т. к. може бути багато полів з однаковим ім'ям):
Тепер про проблеми.
Для початку, поля. Ви привласнюєте значення полів, минаючи властивості. Це не цілком правильно, адже властивості при присвоєнні можуть виконувати якусь логіку, яку ви пропускаєте при вашому підході. (Цю проблему можна частково вирішити, працюючи з властивостями замість полів, але якщо в вашому класі є і поля, що не укладаються на властивості, проблем не уникнути.)
Потім, значення за замовчуванням. Це значення може і не бути хорошим початковим значенням для всіх полів. Якщо ви користуєтеся default (T). то для рядка правильним значенням цілком може виявитися "" або там "(none)". Рефлексія це повністю нівелює.
Далі, з рефлексією ви не зможете відмовитися від обнулення якогось з полів, хіба що вам доведеться вводити атрибути, і змушувати користувача прикріплювати атрибути до полів, що впливають на поведінку обнуляє методу. Це перетворить невинну фичу в цілий фреймворк.