none
C# где объявить объект для его глобальной видимости? RRS feed

  • Вопрос

  • Я понимаю что понятие глобальной переменной в C# нет, но суть в том что при старте программы она загружает настройки в некий объект, далее они повсеместно используются. На данный момент я объявил объект в главной форме, в дочернем окне (SDI интерфейс), AppSettings уже "Не существует в текущем контексте", а передавать повсюду и повсеместно ссылку на объект хранящий переменные как-то излишне.

    Могу ли я объявить объект в где-то в program.cs чтоб он был виден везде?

    • Перемещено Siddharth Chavan 1 октября 2010 г. 21:36 MSDN Forums Consolidation (От:Visual C#)
    24 марта 2010 г. 7:56

Ответы

  • Создавайте экземляр этого класса как статический член любого класса оболочки - поместите этот класс в области видимости всех форм и через статическое свойство спокойно получайте доступ к единственному экземпляру вашего объекта AppSett

        public class AppSetWrapper
        {
             //хранит настройки
             private Settings appSettings;
    
             //конструктор выполняется один раз при запуске приложения
             static AppSetWrapper
             {
                appSettings = Settings.Create(...);
             }
    
             //Получаем доступ к объекту-свойствам
             public static Settings AppSettingsInstance
            {
                get
                {
                    return appSettings;
                }
            }
        }
    
    где - то
    public Form1 : Form
    {
        public void Method()
        {
             MessageBox.Show(AppSetWrapper.AppSettingsInstance)
         }
    }
    
    public Form2 : Form
    {
        public void Method()
        {
             MessageBox.Show(AppSetWrapper.AppSettingsInstance)
         }
    }
    и т.д. Один экземпляр объекта-свойств на все формы во всем приложении, что собственно в начале и было написано.
    • Помечено в качестве ответа PhantomSL 24 марта 2010 г. 16:45
    24 марта 2010 г. 9:07
  • Ну в форму его не надо помещать, зачем - это же глобальные настройки для всего приложения. В принципе его не надо вобще делать вложенным класом, поместите его в то же пространство имен, где ваш класс Program объявлен, хотя бы вот так:

    namespace WindowsFormsApplication2
    {
        static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
        }
    
        public class AppSetWrapper
        {
             //хранит настройки
             private Settings appSettings;
    
             //конструктор выполняется один раз при запуске приложения
             static AppSetWrapper
             {
                appSettings = Settings.Create(...);
             }
    
             //Получаем доступ к объекту-свойствам
             public static Settings AppSettingsInstance
            {
                get
                {
                    return appSettings;
                }
            }
        }
    
    }
    Ну это все дело удобства, а теоретически его куда угодно можно поместить. В частности VS добавляет автоматически пространство имен Properties с кдассом глобальных настроек Settings - его и туда можно поместить.
    • Помечено в качестве ответа PhantomSL 24 марта 2010 г. 13:37
    • Снята пометка об ответе PhantomSL 24 марта 2010 г. 14:09
    • Помечено в качестве ответа PhantomSL 24 марта 2010 г. 16:45
    24 марта 2010 г. 12:56

Все ответы

  • Вот пример

    public class MySettinfg
        {
            private MySettinfg() { }
    
            public string MySetting1
            {
                get
                {
                    return "setting1";
                }
            }
            public string MySetting2
            {
                get
                {
                    return "setting2";
                }
            }
    
            private static MySettinfg instance;
            
            static MySettinfg()
            {
                instance = new MySettinfg();
            }
    
            public static MySettinfg Setting
            {
                get
                {
                    return instance;
                }
            }
        }
    24 марта 2010 г. 8:11
  •  

    Видимо я или не понял сути или не верно задал вопрос, так что вношу дополнения:

    1. Я не нашел более менее вразумительно способа для сохранения настроек в .Net Compact в итоге был написан такой класс:

     

    [Serializable]
        [XmlRootAttribute("Settings", Namespace = "", IsNullable = true)]
        public class Settings
        {
            private string FileName;
            private XmlWriterSettings xws;
    
            private Settings() { } //Обязательное условие для сериализации и значения по умолчанию
    
            public static Settings Create(string SettFileName)
            {
                //Создаем новый экземпляр
                Settings Res = new Settings();
    
                if (File.Exists(SettFileName)) //Если файл существует, то загружаем
                {
                    XmlSerializer serializer = new XmlSerializer(Res.GetType());
    
                    using (Stream SerStream = new FileStream(SettFileName, FileMode.Open))
                    {
                        Res = (Settings)serializer.Deserialize(SerStream);
                    } //SerStream.Close();
                }
                Res.FileName = SettFileName; //Так как обнуляется в процессе сериализации
    
                //Сохранение в нужной мне кодировке
                Res.xws = new XmlWriterSettings();
                Res.xws.Encoding = Encoding.GetEncoding(1251);
                Res.xws.Indent = true;
                return Res;
            }
            
            //Сохранение настроек в файл
            public void Save()
            {
                //Подключаем к потоку вывода
                using (Stream SerStream = new FileStream(FileName, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    XmlWriter xw = XmlWriter.Create(SerStream, xws);
                    XmlSerializer serializer = new XmlSerializer(this.GetType());
                    serializer.Serialize(xw, this);
                    xw.Close();
                } //SerStream.Close();
            }
            
            //Собственно сами сохраняемые переменные
            //Со значениями по умолчанию
            public string IP = "196.68.8.51";//"192.168.1.1";
            public int Port = 9002;
        }
    И он задействуется: в главной форме:
    //Объявление в классе формы
    Settings AppSett;
    //Считываем настройки в Load
    AppSett = Settings.Create(MainPath + "AppSett.txt");
    
    //Сохраняем в Close
    AppSett.Save();
    Так что .Net Compact и условия XML сериализации несколько сдерживают применение статических классов и т.д. Вот я и спрашивал ГДЕ именно объявить Settings Appset чтоб видеть в дочерних формах?
    24 марта 2010 г. 8:41
  • Вам необходимо создать public класс-сингльтон, в который при старте нужно записывать данные и потом использовать где-либо в приложении.

    Как создать класс-сингльтон, описано здесь: http://www.yoda.arachsys.com/csharp/singleton.html

    24 марта 2010 г. 9:03
  • Создавайте экземляр этого класса как статический член любого класса оболочки - поместите этот класс в области видимости всех форм и через статическое свойство спокойно получайте доступ к единственному экземпляру вашего объекта AppSett

        public class AppSetWrapper
        {
             //хранит настройки
             private Settings appSettings;
    
             //конструктор выполняется один раз при запуске приложения
             static AppSetWrapper
             {
                appSettings = Settings.Create(...);
             }
    
             //Получаем доступ к объекту-свойствам
             public static Settings AppSettingsInstance
            {
                get
                {
                    return appSettings;
                }
            }
        }
    
    где - то
    public Form1 : Form
    {
        public void Method()
        {
             MessageBox.Show(AppSetWrapper.AppSettingsInstance)
         }
    }
    
    public Form2 : Form
    {
        public void Method()
        {
             MessageBox.Show(AppSetWrapper.AppSettingsInstance)
         }
    }
    и т.д. Один экземпляр объекта-свойств на все формы во всем приложении, что собственно в начале и было написано.
    • Помечено в качестве ответа PhantomSL 24 марта 2010 г. 16:45
    24 марта 2010 г. 9:07
  • Вам необходимо создать public класс-сингльтон, в который при старте нужно записывать данные и потом использовать где-либо в приложении.

    Как создать класс-сингльтон, описано здесь: http://www.yoda.arachsys.com/csharp/singleton.html


    Посмотрите выше и убедитесь, что у меня и есть непотокобезопасный синглтон.
    24 марта 2010 г. 9:09
  • Такой вариант

     

        public static class MySettings
        {
            public static Dictionary<string, object> Setings
            { get; set; }
            static MySettings()
            {
                Setings = new Dictionary<string, object>();
                Setings.Add("something", "something to put");
            }
        }

     

    Тестируем :
            [Test]
            public void GetSomethigWhatAdedWhenAplicationStart()
            {
                Assert.AreEqual("something to put", (string)MySettings.Setings["something"]);
            }
    
            [Test]
            public void AddSettingsProgrammatically()
            {
                Object objectToPut = new object();
                MySettings.Setings.Add("myObj", objectToPut);
                Assert.AreSame(objectToPut, MySettings.Setings["myObj"]);
            }

     

    24 марта 2010 г. 9:48
  • >> Посмотрите выше и убедитесь, что у меня и есть непотокобезопасный синглтон.

    Убедился. Но, думаю, нужно было описать, почему именно такой код нужно использовать.

    24 марта 2010 г. 10:01
  • >> Посмотрите выше и убедитесь, что у меня и есть непотокобезопасный синглтон.

    Убедился. Но, думаю, нужно было описать, почему именно такой код нужно использовать.


    Да.. в любом случае ответ получен.
    24 марта 2010 г. 10:08
  • "Создавайте экземляр этого класса как статический член любого класса оболочки - поместите этот класс в области видимости всех форм и через статическое свойство спокойно получайте доступ к единственному экземпляру вашего объекта AppSett"

    Я новичек в C# и меня более всего интересует "поместите этот класс в области видимости всех форм"

    1.

    private Settings appSettings
    Может быть полем "static class Program" или "public partial class fmMainForm : Form" если нет, то созданный только для отражения "public class AppSetWrapper" где должен объявляться в файле "program.cs" или в файле содержащем класс формы?

     

    24 марта 2010 г. 11:55
  • Ну в форму его не надо помещать, зачем - это же глобальные настройки для всего приложения. В принципе его не надо вобще делать вложенным класом, поместите его в то же пространство имен, где ваш класс Program объявлен, хотя бы вот так:

    namespace WindowsFormsApplication2
    {
        static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
        }
    
        public class AppSetWrapper
        {
             //хранит настройки
             private Settings appSettings;
    
             //конструктор выполняется один раз при запуске приложения
             static AppSetWrapper
             {
                appSettings = Settings.Create(...);
             }
    
             //Получаем доступ к объекту-свойствам
             public static Settings AppSettingsInstance
            {
                get
                {
                    return appSettings;
                }
            }
        }
    
    }
    Ну это все дело удобства, а теоретически его куда угодно можно поместить. В частности VS добавляет автоматически пространство имен Properties с кдассом глобальных настроек Settings - его и туда можно поместить.
    • Помечено в качестве ответа PhantomSL 24 марта 2010 г. 13:37
    • Снята пометка об ответе PhantomSL 24 марта 2010 г. 14:09
    • Помечено в качестве ответа PhantomSL 24 марта 2010 г. 16:45
    24 марта 2010 г. 12:56
  • А разве статическому конструктору или свойству можно оперировать с не статическими данными коими является appSettings?

    У меня VS ругается на "Для нестатического поля, метода или свойства "DelSmart.AppSetWrapper.appSettings" требуется ссылка на объект"

    24 марта 2010 г. 14:07
  • Судя по всему

    private Settings appSettings тоже надо static


    24 марта 2010 г. 16:26
  • Судя по всему

    private Settings appSettings тоже надо static



    Ага, я просто так набивал - не компилил, поэтому прошла ошибка.

    24 марта 2010 г. 21:16