Возник у меня такой концептуальны вопрос. Предположим у меня есть приложение, которое при запуске загружает в некий объект (mySettings) локальные настроки. В дальнейшим чуть ли не каждая форма бдет обращаться к этим настройкам.
Как лучше все это дело организовать. Банально, напрашивается создать этот объект на главной форме, а после этого передавать его в качестве параметра в конструктор каждой формы. Но так, естественно, неудобно. Я прямо таки чуствую, что можно сделать проще и удобнее... Например через статический "глобальный" класс.
Вообщем, в связи с тем, что на .Net я пишу совсем недавно, прошу подсказать как делать лучше, чтобы не наступать на уже обхоженные грабли.
Лучше сделать статический класс Settings и создать у него статический конструктор, в котором загрузить все необходимые параметры и разложить по статическим же переменным класса.
Я бы создал класс с настройками и создал форму "A", которая содержит экземпляр этого класса. Все формы, использующие настройки, унаследуют сво-ва и методы от объявленной формы "A" и автоматически получают адрес на объект с настройками.
Тогда выйдет следующее: каждый раз, когда вы создаете форму, указывая родительскую, с уже загруженными настройками, дочерняя форма сама забирает настройки у материнской формы.При таком подходе при создании новой формы вы даже вспоминать не будете про загрузку настроек.
Опа! А можно немного поподробнее? Если можно, то с примером.
Придположим у меня есть форма:
public class Form1 : System.Windows.Forms.Form
{
//.......
public Settings lSettings;
public MainFrm()
{
InitializeComponent();
lSettings = new Settings();
//.......
}
//.......
}
ака, лана, попытаюсь изобразить, хотя на самом деле тут целый walkthrought надо написать, так как сам я все мышой стараюсь делать:
/////Описание базовой формы, которая умеет работать с настройками.
public class A : System.Windows.Forms.Form
{
public Settings set;
public MainFrm()
{
InitializeComponent();
try
{
A a = (A)parent;
this.set = a.set;
}
catch
{///Ну, а если catch вызывается соответственно либо это самая рутовская форма, либо настроек нету:)
}
}
}
////Далее "рабочий" код
////Форма, которая изображает модальный дилог:
class Form2:A
{
...
///Тут не важно что, так как форма унаследована от "A", и "A" сама примет настройки
}
////Первая форма, рутовская, с нее начинается работа програмы:
class Form1 : A
{
...
public void Form1_OnLoad(...)
{
////Загружаем настройки в this.set;
}
public void SomeEvent(...)
{////Сдесь создаем дочернюю форму, которая получит настройки автоматически
Form2 dlg = new Form2();////на этом этапе dlg возьмет из парента(this) настройки, так как эта форма уже загрузила настройки и является произвожной от "A"
dlg.showDialog(this)/////А кстати можно еще перегрузить метод ShowDialog, если это уместно, и вставить код для чтения настроек из родителя прям там, а не при инициализации.
Hello, "mslava" > Лучше сделать статический класс Settings и создать у него статический конструктор, в котором загрузить все необходимые параметры и разложить по статическим же переменным класса. >
Лучше делать не статический класс Settings, а обычный Singeton класс вида:
[c#]
class Settings
{
public static readonly Settings Instance = new Settings();
// Загрузить настройки тут
private Settings()
{
}
}
[c#]
Обращаться к нему через Settings.Instance.Filed1
Posted via RSDN NNTP Server 1.9
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re: Как лучше сделать?
От:
Аноним
Дата:
16.01.05 16:00
Оценка:
Статические переменные и методы — дурной тон.А вот тема с унаследованием — это тема.Можно это унаследуемую форму в dll скомпилить, и при надобности (например, изменить способ загрузки настроек) переделывать не саму программу, а лишь этот самый dll.
Hello, "jinek" > Статические переменные и методы — дурной тон.А вот тема с унаследованием — это тема.Можно это унаследуемую форму в dll скомпилить, и при надобности (например, изменить способ загрузки настроек) переделывать не саму программу, а лишь этот самый dll. >
Что касается статических переменных и методов, то это предрассудок (примерно как goto), который который поддерживается специально, чтобы начинающие программисты использовали возможности ООП, а не скатывались к обычному процедурному программированию.
Между тем, если подумать, то можно придти к вызову, что кроме объектов есть еще контекст с которым они связаны. И, информацию, которая имеет отношение к группе объектов лучше хранить не в иерархии (которая может иметь абсолютно другую предметную обсласть), а поместить в контекст. Контекстом может быть как специальная структура, TLS, так и общие данные на уровне AppDomain
Posted via RSDN NNTP Server 1.9
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Как лучше сделать?
От:
Аноним
Дата:
16.01.05 20:49
Оценка:
>ака, лана, попытаюсь изобразить, хотя на самом деле тут целый walkthrought надо написать, так как сам я все мышой стараюсь делать:
Так... поковыряв и пораскинув мозгами я кое-чего понял =) Итак. Мы создаем некий класс, от которого наследуются все формы проекта (ну, или только те, которые надо). Дальше — хуже. parent у меня почему-то не доступен, а Parent — всегда равен null. Но это не беда. Получилось как в том анекдоте. Не Parent, а Owner и не в конструкторе а на Load. Итого: Я создал некую базовую форму:
public class BaseForm : System.Windows.Forms.Form
{
//............
public MySettings Settings;
Далее в главной (корневой/первой) форме создаю необходимый объект. Остальные формы создаю кодом что-то типа
Form1 f = new Form1();
f.ShowDialog(this);
Собственно, оно все работает и мне такой вариант нравится, потому что объект с настройками не единственный объект, который мне понадобиться в большинстве форм. Но несколько смущает, что из конструктора у меня еще не доступен нужный мне объект. Поправьте где я не прав.
Дальше... Как я понимаю, такой подход оправдан только в случае если это объект мне нужен из абсолютного большинства форм. В противном случае — либо создавать еще одну форму для наследования в редких случаях (например наследник от BaseForm) либо использовать статические свойства некоторого класса (кстати, тоже попробовал и все прекрасно работает и устраивает). Но мне он не очень нравится с эстетической точки зрения...
Кстати, Тимофей еще упоминал про "TLS, и общие данные на уровне AppDomain". Можно и про них пару слов? =)
---
кстати, я чего-то не нашел здесь инструкцию, как красиво оформлять исходники и вставлять цитировани =( Хоть и offtopic, но хоть на мыло скиньте ссылочку, pls.
1)Передавайте родителя в конструкторе, тогда он будет уже доступен везде.
2)Я всегда parent использовал, странно...
3)Кода вы напишете только на 5-6 строчки больше, и это максимум, при только двух формах, далее строчек получится уже меньше, так что сами считайте: оправдан или не оправдан.
4)Зачем еще форму для наследования создавать???, просто не унаследовать эту и все....
Hello, "Petrakov D" > > Собственно, оно все работает и мне такой вариант нравится, потому что объект с настройками не единственный объект, который мне понадобиться в большинстве форм. Но несколько смущает, что из конструктора у меня еще не доступен нужный мне объект. Поправьте где я не прав. >
Это все потому, что идея поместить в корневой экземпляр иерархии какие-то общие настройки не самая лучшая идея. Уже сейчас видно, что дальше будет еще хуже.
> Дальше... Как я понимаю, такой подход оправдан только в случае если это объект мне нужен из абсолютного большинства форм. В противном случае — либо создавать еще одну форму для наследования в редких случаях (например наследник от BaseForm) либо использовать статические свойства некоторого класса (кстати, тоже попробовал и все прекрасно работает и устраивает). Но мне он не очень нравится с эстетической точки зрения... >
Да, использование статических свойств стоит минимизировать. Между тем, есть такой паттерн, как Singleton — это вполне нормальное решение для подобных задач.
> Кстати, Тимофей еще упоминал про "TLS, и общие данные на уровне AppDomain". Можно и про них пару слов? =) >
Общие данные на уровне AppDomain это аналог статических полей. TLS это Thread Local Storage любое static поле можно пометить атрибутом ThreadStaticAttribute — тогда оно будет глобальным на уровне потока.
Кроме статических полей можно использоать AppDomain.CurrentDomain.GetData/SetData (данные будут доступны всем объектам домена), либо Thread.CurrentThread.GetData/SetData (данные будут доступны только для текущего потока, а форма всегда работает в том потоке, в котором ее создали). Кстати, Thread.CurrentThread и AppDomain.CurrentDomain — это аналоги статических свойств. как говорится, решение от "ведущих сабаководов".
Что касается эстетики, то в общем случае с ней можно бороться использованием инкапсуляции:
Например, в ASP.NET у страницы есть свойство this.Request, но при этом, тотже самый объект можно получить через HttpContext.Current.Request...
> кстати, я чего-то не нашел здесь инструкцию, как красиво оформлять исходники и вставлять цитировани =( Хоть и offtopic, но хоть на мыло скиньте ссылочку, pls. >
Могу рассказать, как это делается на RSDN
Posted via RSDN NNTP Server 1.9
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[2]: Как лучше сделать?
От:
Аноним
Дата:
17.01.05 04:55
Оценка:
Вот откуда вы набрались такого бреда, что статические классы это дурной той? Смешно вас читать.
В C# 2.0 статик классы тоже специально для совместимости ввели?
Без них как-то же живем сейчас и ничего.
По поводу конфига:
В общем случае это сильно криво завязывать конфиг на формы.
Никаких WindowsForms в общем случае может не быть.
Хороший вариант либо со статиком либо с синглтоном.
Какие-то слова про контекст очень мало имеют общего с поставленной задачей. Задача была — загружать локальные настройки