Question about making object instance visible to other objects

I have 3 classes:

MainClass
SettingsClass
FormClass

Now, Mainclass handles most operations and does it's job well, upon being instantiated it creates an instance of SettingsClass, we'll call this instance _settings.  SettingsClass holds global settings for the application... like the user name, state of various things, that sort of stuff.  During the lifetime of MainClass, a FormClass may or may not be instantiated as well.  FormClass needs to be able to access _settings (the same instance of SettingsClass that MainClass uses).  At first, I was making the constructor for FormClass take a reference of SettingsClass, which seems to work ok partly.  Something like this:

public partial class FormClass : Form
{
     private SettingsClass _refSettings;

     public FormClass(ref SettingsClass s)
     {
          _refSettings = s;
     }

    // The rest of the form stuff here of course
}

And whenever (if ever) FormClass gets created, it would look like this:

public class MainClass
{
     private SettingsClass _settings;
     private FormClass _form;

     public MainClass()
     {
          _settings = new SettingsClass();
     }

     // In some function...
     {
          _form = new FormClass(ref _settings);
          _form.Show();
     }
}

This seems really weird though, I'm sure there are better ways to make my instance of _settings visible to _form, or I assume so at least.  Any ideas

Also, if the way I'm currently doing it is the only/best way, how do I properly dispose of _refSettings when the instance of FormClass goes away   Would doing _refSettings = null;  actually destroy the object, or would it only destroy the reference itself, thus allowing _settings to be used again and again as many times as FormClass gets instantiated during the lifetime of MainClass

It's getting really confusing to me, not sure how to handle this.  In summary, I just want to be able to read/modify an instance SettingsClass from another class that was created in the same scope.

Any help would be appreciated.

Brandon


Answer this question

Question about making object instance visible to other objects

  • Leho

    Another question regarding this. Since my Settings class holds useful information, it would also be useful if I could serialize and deserialize it (to XML) when the application starts/stops. If I created a destructor for the singleton to serialize it before it's destroyed, would that destructor ever get called If this would work, I'd also obviously alter it a bit so that the constructor properly deserializes it as well.

  • Cheers

    Thanks a ton, this should work perfectly! Every time I think I'm getting a good grasp on the C# and .NET world, something new and interesting gets shown to me, I am indebted to you!

  • SnakeLair

    Hmm, a bit confused by that. There is no definite user interface. This mostly runs in the background, receiving events from a COM client, and acting accordingly. The Settings instance contains relavent information like username, etc. Whenever any part of my code references the Settings singleton, I want it to be retrieving the correct information, regardless of whether or not the program was first loaded. I was thinking of changing the static constructor to:

    // Static constructor to initialize the global settings instance
    static Settings()
    {
    try
    {
    // Attempt to deserialize the previous settings.
    _instance = (Settings)the deserialized object;
    } catch {
    // If deserialization fails, we go ahead and create the empty Settings
    _instance = new Settings();
    }
    }

    This would retrieve the old settings whenever the singleton is referenced for the first time I believe, my problem is where to actually serialize it at. I'm not totally sure when a deconstructor would get called with a singleton, since I'm using it "lazily" and never actually explicitly create the instance in my other code.

    Thanks Blair, always a help!

  • Dick Schroth

    you need to implement a singleton pattern on Settings:

    nb: code just spit out, might have errors

    public class Settings
    {
     
         // this is the global instance
         private static Settings _instance;
         private int _timeOutMs;

         // Static constructor to initialize the global settings instance
         static Settings(){  _settings = new Settings(); }
         
         
    // Private constructor prevents multiple instancing
         public Settings(){}
         
         // Access settings through the static instance
     
        public static Settings Instance
         {
             get
             {
                   return _instance;
             }
         }

         //A particular setting (Time-Out in Milliseconds) 
         public uint TimeOutMs
         {
             get
             {
                   return _timeOutMs;
             }
             set
             {
                   _timeOutMs = value;
             }
         }

    }

    public partial class MyForm: Form
    {
          public MyForm(){}         

          protected override OnLoad(EventArgs e)
          {
              MessageBox.Show(string.format("Timeout (mS): {0}",
                          Settings.Instance.TimeOutMs.ToString()));
          }
    }

    public class MyFormController
    {
         private MyForm _form;

         public MyFormController()
         {
             Settings.Instance.TimeOutMs = 2000;
         }

         public void ShowMyForm()
          {
              _form = new MyForm();
              _form.Show();
         }
    }



  • dimondlight

    on thing you could do is use the XML editor to create a "settings" typed datatable this would give you the save and load to xml.

    Typically the pattern would be

    LoadSettings

    SaveSettings

    LoadDefaults

    you would present a user interface showing the current settings. Have a button to load defaults (defined in your xml), restore current, and save settings. Saving would only be done when the UI closes.

    Still use the Singleton Pattern to present your typed datatable.

    make sense



  • Mike Lavender

    Blair,

    Here is what I've come up with, and it seems to work perfectly so far!  Let me know what you think, efficiency-wise, etc!

        public class Settings
        {
            #region Singleton Stuff
            private CharacterSettings()
            {
             }

            public static Settings Instance
            {
                get
                {
                    return NestedSingleton._instance;
                }
            }

            private class NestedSingleton
            {
                internal static readonly Settings _instance;
              
                static NestedSingleton()
                {
                    try
                    {
                        XmlSerializer s = new XmlSerializer(typeof(Settings));
                        TextReader r = new StreamReader(@"C:\Settings.xml");
                        _instance = (Settings)s.Deserialize(r);
                        r.Close();
                        System.Windows.Forms.MessageBox.Show("Settings loaded.");
                    }
                    catch
                    {
                        _instance = new Settings();
                        System.Windows.Forms.MessageBox.Show("Settings created.");
                    }
                }
            }
            #endregion

            #region Methods
            public void Serialize()
            {
                XmlSerializer s = new XmlSerializer( typeof(Settings));
                TextWriter w = new StreamWriter(@"C:\Settings.xml");
                s.Serialize(w, Settings.Instance);
                w.Close();
            }
            #endregion

        }

    In my main application, in my equivalent to the OnClosing method of a form (again, I'm communicating with a COM client, whos interface has a specific method that is called right before the main application closes).  I simply do:

    Settings.Instance.Serialize();


    When I run the application for the first time, I successfully receive the "Settings created." message box, when I close the application I successfully receive the "Settings saved." box, and when I re-run it, I get the "Settings loaded." box and the settings are indeed the same.  So it appears to be working!  I did change singleton pattern's design around a bit, based on the article here:  http://www.yoda.arachsys.com/csharp/singleton.html

    Does this look efficient

  • caeriel

  • Question about making object instance visible to other objects