Implementation of Singleton

  • Thread starter Thread starter Tony W
  • Start date Start date
T

Tony W

Hi,

I'm trying to write a small app where I need to keep referencing a
stored file location that is stored in an xml file.

My research suggests that I should use a Singleton to store the file
path and use the Singleton each time I need the path string.

I am new to c# so have looked at numerous examples of creating a
Singleton. Although there are dozens of webpages with examples, most
are just copies of about 4 different webpages.
None of these clearly explain how to implement the storage and
retrieval of data values using a Singleton, only how to get an
instance and then see if you can get a second instance.

I have tried using trial and error editing the examples I have found
but this has not worked.

Could someone please point me in the direction of a good example or
post one in the ng?

If I haven't made myself clear or you need further info please ask.

Many thanks,

Tony W
 
Tony said:
Hi,

I'm trying to write a small app where I need to keep referencing a
stored file location that is stored in an xml file.

My research suggests that I should use a Singleton to store the file
path and use the Singleton each time I need the path string.

I am new to c# so have looked at numerous examples of creating a
Singleton. Although there are dozens of webpages with examples, most
are just copies of about 4 different webpages.
None of these clearly explain how to implement the storage and
retrieval of data values using a Singleton, only how to get an
instance and then see if you can get a second instance.
Well the retrieval you would probably do in your constructor which would
be private.

For the storage, maybe put a save method on your class that can be
called when the application exits.

I dont have any examples but have done this in the past, deserializing
and serializing in this manner as circumstances call.
I have tried using trial and error editing the examples I have found
but this has not worked.
Maybe if you post some of your trials and explain the problems you had/have.

Cheers
JB
 
John,

The storage is not a problem as I don't want to change the value held
whilst the application is in use. I intend to get changes and save
them until the app is restarted to apply them.

I have the following code for the Singleton but don't know how to use
the value from my main class. As you will be able to tell, most of
the code is from examples found on the internet with additions.

code start~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

namespace AVDat
{
public sealed class DebugLog
{
private static readonly DebugLog instance = new DebugLog();
private static string debugLogPath;

// make the default constructor private, so that no can_
directly create it.
private DebugLog()
{
//code here to get location of debug log from xml file
//create dataset
DataSet dsLogLoc = new DataSet();
dsLogLoc.ReadXml(@"C:\LogFileLocs.xml");
DataTable dtDbLogLoc = dsLogLoc.Tables["DebugLog"];

debugLogPath = dtDbLogLoc.Rows[0][1].ToString();
}

// public property that can only get the single instance of
this class.
public static DebugLog Instance
{
get
{
return instance;
}
}
}

code end~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When my app starts I want to get the string value and use it
throughout my app to log different functions used by the user in a
debug log. I have a method for writing to the log, I just need to get
the value into the debuglog so that I don't have to hardcode the
logfile path.

Method code below - edited.

code start~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public static void WriteToAppLog (string logMessage, uint modeFormat)
{
string currentTime = DateTime.Now.ToLongTimeString() + '\t';
string currentDate = DateTime.Now.ToLongDateString() + '\t';
StreamWriter w = File.AppendText(@"C:\\AppLog.txt");
try
{
if (modeFormat == 1)
{
WRITE TO LOG FILE
}
else if(modeFormat == 2)
{
WRITE DIFFERENT TEXT TO LOGFILE
}
else
{
WRITE DEFAULT TEXT TO LOGFILE;
}
}
catch (Exception excep)
{
WRITE TO APP LOG
}
finally
{
// Update the underlying file.
w.Flush();
w.Close();
}
}

code end~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Hope you can help otherwise I will have to resort to getting path and
putting it into a hidden textbox on the form, crude but works.

Thanks again,

Tony W
 
Tony said:
John,

The storage is not a problem as I don't want to change the value held
whilst the application is in use. I intend to get changes and save
them until the app is restarted to apply them.

I have the following code for the Singleton but don't know how to use
the value from my main class. As you will be able to tell, most of
the code is from examples found on the internet with additions.

Ok, How about this

public sealed class DebugLog
{
private static readonly DebugLog m_Instance;

private string m_LogPath;
private DebugLog()
{
//m_LogPath = read value from config or whatever
}

public static DebugLog Instance
{
get
{
return m_Instance;
}
}

public string LogPath
{
get
{
return m_LogPath;
}
set
{
m_LogPath = value;
}
}

public void WriteToLog(string logMessage, uint modeFormat)
{
//write to the log
}
}

Then in your main form or wherever you can get the debuglog path by

string Path = DebugLog.Instance.LogPath;


Write to the log file by

DebugLog.Instance.WriteToLog(blah, blah);


Does this help?

JB
code start~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

namespace AVDat
{
public sealed class DebugLog
{
private static readonly DebugLog instance = new DebugLog();
private static string debugLogPath;

// make the default constructor private, so that no can_
directly create it.
private DebugLog()
{
//code here to get location of debug log from xml file
//create dataset
DataSet dsLogLoc = new DataSet();
dsLogLoc.ReadXml(@"C:\LogFileLocs.xml");
DataTable dtDbLogLoc = dsLogLoc.Tables["DebugLog"];

debugLogPath = dtDbLogLoc.Rows[0][1].ToString();
}

// public property that can only get the single instance of
this class.
public static DebugLog Instance
{
get
{
return instance;
}
}
}

code end~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When my app starts I want to get the string value and use it
throughout my app to log different functions used by the user in a
debug log. I have a method for writing to the log, I just need to get
the value into the debuglog so that I don't have to hardcode the
logfile path.

Method code below - edited.

code start~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public static void WriteToAppLog (string logMessage, uint modeFormat)
{
string currentTime = DateTime.Now.ToLongTimeString() + '\t';
string currentDate = DateTime.Now.ToLongDateString() + '\t';
StreamWriter w = File.AppendText(@"C:\\AppLog.txt");
try
{
if (modeFormat == 1)
{
WRITE TO LOG FILE
}
else if(modeFormat == 2)
{
WRITE DIFFERENT TEXT TO LOGFILE
}
else
{
WRITE DEFAULT TEXT TO LOGFILE;
}
}
catch (Exception excep)
{
WRITE TO APP LOG
}
finally
{
// Update the underlying file.
w.Flush();
w.Close();
}
}

code end~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Hope you can help otherwise I will have to resort to getting path and
putting it into a hidden textbox on the form, crude but works.

Thanks again,

Tony W

Well the retrieval you would probably do in your constructor which would
be private.

For the storage, maybe put a save method on your class that can be
called when the application exits.

I dont have any examples but have done this in the past, deserializing
and serializing in this manner as circumstances call.



Maybe if you post some of your trials and explain the problems you had/have.

Cheers
JB
 
John B said:
Ok, How about this

public sealed class DebugLog
{
private static readonly DebugLog m_Instance;

private string m_LogPath;
private DebugLog()
{
//m_LogPath = read value from config or whatever
}

public static DebugLog Instance
{
get
{
return m_Instance;
}
}

<snip>

One problem - you never set m_Instance to anything, so it will always
be null, and no instances will ever be created...
 
Jon said:
<snip>

One problem - you never set m_Instance to anything, so it will always
be null, and no instances will ever be created...
Doh, you are quite right.


Tony
Read Jon's Singleton page, very informative.
http://www.yoda.arachsys.com/csharp/singleton.html

Try

if(m_Instance == null)
{
m_Instance = new DebugLog();
//Question Jon, can you set a readonly field like this? Havent tried, no
time at the mo, will try later.
}

If this does not work, or just because you want to, use:
private static readonly DebugLog m_Instance = new DebugLog();

JB
:)
 
John B said:
if(m_Instance == null)
{
m_Instance = new DebugLog();
//Question Jon, can you set a readonly field like this? Havent tried, no
time at the mo, will try later.
}

No - but the above isn't thread-safe anyway :) (You'd need to lock on
something for the duration of the property call.)
If this does not work, or just because you want to, use:
private static readonly DebugLog m_Instance = new DebugLog();

That's much better - you could even just make it

public static readonly DebugLog Instance = new DebugLog();

and get rid of the property entirely, if you're convinced you'll never
want to do anything else.
 
Jon said:
No - but the above isn't thread-safe anyway :) (You'd need to lock on
something for the duration of the property call.)

I know it isnt thread safe ;)
thanks to some initial reading and thinking re your singleton page.
That's much better - you could even just make it

public static readonly DebugLog Instance = new DebugLog();

and get rid of the property entirely, if you're convinced you'll never
want to do anything else.

Im never convinced that Ill never want to do anything else ;)

Thanks for the input
JB
 
Hi,

Thanks for all the input but it has now gone way over my head. I only
have a basic understanding of classes and was hoping that I would be
able to learn as I went along.

I have already seen the webpage recommended but this doesn't tell you
how to use a Singleton in practice, just how to create it. Maybe I
just don't have the experience yet.

I initially wanted to use a global variable to hold the location of
the log file. This is simple as you set its value once and then use
it wherever you want. As the value will never change there is very
little risk of the set value becoming corrupt.

I know that the general concensus is that global variables are 'bad'
so I looked on the internet and discovered Singletons were a suggested
option. This is why I have arrived at this point. Why are global
variables considered 'bad', surely they have a place. Why add loads
of extra code that needs executing when it isn't needed?

Your thoughts and advice are really appreciated, please help further.

Many thanks,

Tony W
 
Tony said:
Hi,

Thanks for all the input but it has now gone way over my head. I only
have a basic understanding of classes and was hoping that I would be
able to learn as I went along.

I have already seen the webpage recommended but this doesn't tell you
how to use a Singleton in practice, just how to create it. Maybe I
just don't have the experience yet.

I initially wanted to use a global variable to hold the location of
the log file. This is simple as you set its value once and then use
it wherever you want. As the value will never change there is very
little risk of the set value becoming corrupt.

I know that the general concensus is that global variables are 'bad'
so I looked on the internet and discovered Singletons were a suggested
option. This is why I have arrived at this point. Why are global
variables considered 'bad', surely they have a place. Why add loads
of extra code that needs executing when it isn't needed?

Your thoughts and advice are really appreciated, please help further.

Many thanks,

Hi Tony,
E-mail me to

johnbaro
at
gmail
..
com

and I will email you a zipped working sample of a singleton and its
usage if that will help.
Its always easier to "see" a working sample.
You are on the right track BTW with using a singleton for "global"
config details (IMO).
:)
Cheers
JB
 
Back
Top