newbie: How to construct Singleton pattern?

D

deko

I need retrieve a DataSet from XML and make it globally accessible. There
are various forms and objects in my WinForms app that need to perform CRUD
operations on this DataSet. I'd like to consolidate all
deserialization/serialization code in the Singleton class, which creates the
DataSet, and use other objects in the DataAccess layer (e.g. a Factory) to
hand out objects to the Forms and perform the CRUD operations.

I've researched the Singleton pattern but could not find any real-world
examples that I could adapt. What I've come up with below is a first crack
at it.

The unanswered questions I have are:

* Should the DataSet creation code be in the constructor of the Singleton
class?
* Should projectDataSet be a public property of the Singleton class?

The problems with my code (the ones I know about) are:

* The DataSet creation code in the getProjectData method (line 38) has a
problem with the if-else statement (lines 52 - 61) - I'm returning a null
reference to projectData (line 60).

* The serialization method (line 70) also has a problem - it serializes a
new, empty DataSet.

How do I resolve these problems? Should I make the DataSet a public
property?

Note: In the getProjectData method, I need to include logic that says: If
the xml file has been validated, then deserialize it into a DataSet; if not,
create the whole thing over again (ProjectDataSet does this), with schema,
and start anew with an empty DataSet. The validation code is in a separate
(TODO) method (line 70). Also, the Singleton is designed to be thread safe
because a separate BackgroundWorker thread needs to use it to get it's own
copy of the DataSet (from xml, not the existing one) to work with.

Thanks in advance.

1 using System;
2 using System.Text;
3 using System.Reflection;
4 using System.Collections;
5 using System.Xml.Serialization;
6 using System.Data;
7 using System.IO;
8 namespace ASA
9 {
10 sealed class ProjectDataAccess
11 {
12 static ProjectDataAccess instance = null;
13 static readonly object objlock = new object();
14 private const string XML_FILE = "\\projectdata.config";
15 private const string XML SCHEMA = "\\projectdata.xsd";
16 private static string xmlPath = Path.GetDirectoryName (Assembly.
17 GetExecutingAssembly().GetModules()[0].FullyQualifiedName);
18 private ProjectDataAccess()
19 {
20 }
21 public static ProjectDataAccess Instance
22 {
23 get
24 {
25 //if (instance == null)
26 //{
27 lock (obj lock)
28 {
29 if (instance == null)
30 }
31 instance = new ProjectDataAccess();
32 {
33 return instance;
34 }
35 //}
36 }
37 }
38 public static DataSet getProjectData()
39 {
40 string xmlFile = string.Concat(xmlPath, XML_FILE);
41 string xmlSchema = string.Concat(xmlPath, XML_SCHEMA);
42 DataSet projectData = new DataSet();
43 if (cantRead(xmlFile))
44 }
45 ProjectDataSet pds = new ProjectDataSet();
46 projectData = pds.getNewDataSetQ;
47 projectData.WriteXmlSchema(xmlSchema);
48 return projectData;
49 }
50 else
51 {
52 if (projectData == null)
53 }
54 projectData = new DataSetQ;
55 proj ectData.ReadXml (xmlFile);
56 return projectData;
57 {
58 else
59 }
60 return projectData;
61 }
62 }
63 }
64 private static bool cantRead(string xmlFile)
65 {
66 //TODO write validation code
67 return false;
68 //return true;
69 }
70 public static void serializeDataset()
71 {
72 Dataset projectData = ProjectDataAccess.getProjectData;
73 string xmlFile = string.Concat(xmlPath, XML_FILE);
74 Xmlserializer ser = new Xmlserializer(typeof(Dataset));
75 TextWriter writer = new Streamwriter(xmlFile);
76 ser.Serialize(writer, projectData);
77 writer.Close();
78
78 //dsdebug.debugwriteLine (projectData, projectData.DataSetName);
80 }
81 }
82}

Here is the same code without line numbers:

using System;
using System.Text;
using System.Reflection;
using System.Collections;
using System.Xml.Serialization;
using System.Data;
using System.IO;
namespace ASA
{
sealed class ProjectDataAccess
{
static ProjectDataAccess instance = null;
static readonly object objlock = new object();
private const string XML_FILE = "\\projectdata.config";
private const string XML_SCHEMA = "\\projectdata.xsd";
private static string xmlPath = Path.GetDirectoryName(Assembly.
GetExecutingAssembly().GetModules()[0].FullyQualifiedName);
private ProjectDataAccess()
{
}
public static ProjectDataAccess Instance
{
get
{
//if (instance == null)
//{
lock (objlock)
{
if (instance == null)
{
instance = new ProjectDataAccess();
}
return instance;
}
//}
}
}
public static DataSet getProjectData()
{
string xmlFile = string.Concat(xmlPath, XML_FILE);
string xmlSchema = string.Concat(xmlPath, XML_SCHEMA);
DataSet projectData = new DataSet();
if (cantRead(xmlFile))
{
ProjectDataSet pds = new ProjectDataSet();
projectData = pds.getNewDataSet();
projectData.WriteXmlSchema(xmlSchema);
return projectData;
}
else
{
if (projectData == null)
{
projectData = new DataSet();
projectData.ReadXml(xmlFile);
return projectData;
}
else
{
return projectData;
}
}
}
private static bool cantRead(string xmlFile)
{
//TODO write validation code
return false;
//return true;
}
public static void serializeDataSet()
{
DataSet projectData = ProjectDataAccess.getProjectData();
string xmlFile = string.Concat(xmlPath, XML_FILE);
XmlSerializer ser = new XmlSerializer(typeof(DataSet));
TextWriter writer = new StreamWriter(xmlFile);
ser.Serialize(writer, projectData);
writer.Close();

dsdebug.debugWriteLine(projectData, projectData.DataSetName);
}
}
}
 
D

Dazzola

Hi deko

The class you would create to implement the Singlton pattern is very
similar to a regular class. So stuff like the DataSet creation code
would still be handled by methods and properties within the class.

The crucial difference when using the Singlton pattern is in the class
constructor. When something tries to instantiate the class the class
contructor checks to see if it has already been instantiated. If not it
returns a new class object, however if it has been previously
instantiated it just returns a reference to the existing class object.
I need retrieve a DataSet from XML and make it globally accessible. There
are various forms and objects in my WinForms app that need to perform CRUD
operations on this DataSet. I'd like to consolidate all
deserialization/serialization code in the Singleton class, which creates the
DataSet, and use other objects in the DataAccess layer (e.g. a Factory) to
hand out objects to the Forms and perform the CRUD operations.

I've researched the Singleton pattern but could not find any real-world
examples that I could adapt. What I've come up with below is a first crack
at it.

The unanswered questions I have are:

* Should the DataSet creation code be in the constructor of the Singleton
class?
* Should projectDataSet be a public property of the Singleton class?

The problems with my code (the ones I know about) are:

* The DataSet creation code in the getProjectData method (line 38) has a
problem with the if-else statement (lines 52 - 61) - I'm returning a null
reference to projectData (line 60).

* The serialization method (line 70) also has a problem - it serializes a
new, empty DataSet.

How do I resolve these problems? Should I make the DataSet a public
property?

Note: In the getProjectData method, I need to include logic that says: If
the xml file has been validated, then deserialize it into a DataSet; if not,
create the whole thing over again (ProjectDataSet does this), with schema,
and start anew with an empty DataSet. The validation code is in a separate
(TODO) method (line 70). Also, the Singleton is designed to be thread safe
because a separate BackgroundWorker thread needs to use it to get it's own
copy of the DataSet (from xml, not the existing one) to work with.

Thanks in advance.

1 using System;
2 using System.Text;
3 using System.Reflection;
4 using System.Collections;
5 using System.Xml.Serialization;
6 using System.Data;
7 using System.IO;
8 namespace ASA
9 {
10 sealed class ProjectDataAccess
11 {
12 static ProjectDataAccess instance = null;
13 static readonly object objlock = new object();
14 private const string XML_FILE = "\\projectdata.config";
15 private const string XML SCHEMA = "\\projectdata.xsd";
16 private static string xmlPath = Path.GetDirectoryName (Assembly.
17 GetExecutingAssembly().GetModules()[0].FullyQualifiedName);
18 private ProjectDataAccess()
19 {
20 }
21 public static ProjectDataAccess Instance
22 {
23 get
24 {
25 //if (instance == null)
26 //{
27 lock (obj lock)
28 {
29 if (instance == null)
30 }
31 instance = new ProjectDataAccess();
32 {
33 return instance;
34 }
35 //}
36 }
37 }
38 public static DataSet getProjectData()
39 {
40 string xmlFile = string.Concat(xmlPath, XML_FILE);
41 string xmlSchema = string.Concat(xmlPath, XML_SCHEMA);
42 DataSet projectData = new DataSet();
43 if (cantRead(xmlFile))
44 }
45 ProjectDataSet pds = new ProjectDataSet();
46 projectData = pds.getNewDataSetQ;
47 projectData.WriteXmlSchema(xmlSchema);
48 return projectData;
49 }
50 else
51 {
52 if (projectData == null)
53 }
54 projectData = new DataSetQ;
55 proj ectData.ReadXml (xmlFile);
56 return projectData;
57 {
58 else
59 }
60 return projectData;
61 }
62 }
63 }
64 private static bool cantRead(string xmlFile)
65 {
66 //TODO write validation code
67 return false;
68 //return true;
69 }
70 public static void serializeDataset()
71 {
72 Dataset projectData = ProjectDataAccess.getProjectData;
73 string xmlFile = string.Concat(xmlPath, XML_FILE);
74 Xmlserializer ser = new Xmlserializer(typeof(Dataset));
75 TextWriter writer = new Streamwriter(xmlFile);
76 ser.Serialize(writer, projectData);
77 writer.Close();
78
78 //dsdebug.debugwriteLine (projectData, projectData.DataSetName);
80 }
81 }
82}

Here is the same code without line numbers:

using System;
using System.Text;
using System.Reflection;
using System.Collections;
using System.Xml.Serialization;
using System.Data;
using System.IO;
namespace ASA
{
sealed class ProjectDataAccess
{
static ProjectDataAccess instance = null;
static readonly object objlock = new object();
private const string XML_FILE = "\\projectdata.config";
private const string XML_SCHEMA = "\\projectdata.xsd";
private static string xmlPath = Path.GetDirectoryName(Assembly.
GetExecutingAssembly().GetModules()[0].FullyQualifiedName);
private ProjectDataAccess()
{
}
public static ProjectDataAccess Instance
{
get
{
//if (instance == null)
//{
lock (objlock)
{
if (instance == null)
{
instance = new ProjectDataAccess();
}
return instance;
}
//}
}
}
public static DataSet getProjectData()
{
string xmlFile = string.Concat(xmlPath, XML_FILE);
string xmlSchema = string.Concat(xmlPath, XML_SCHEMA);
DataSet projectData = new DataSet();
if (cantRead(xmlFile))
{
ProjectDataSet pds = new ProjectDataSet();
projectData = pds.getNewDataSet();
projectData.WriteXmlSchema(xmlSchema);
return projectData;
}
else
{
if (projectData == null)
{
projectData = new DataSet();
projectData.ReadXml(xmlFile);
return projectData;
}
else
{
return projectData;
}
}
}
private static bool cantRead(string xmlFile)
{
//TODO write validation code
return false;
//return true;
}
public static void serializeDataSet()
{
DataSet projectData = ProjectDataAccess.getProjectData();
string xmlFile = string.Concat(xmlPath, XML_FILE);
XmlSerializer ser = new XmlSerializer(typeof(DataSet));
TextWriter writer = new StreamWriter(xmlFile);
ser.Serialize(writer, projectData);
writer.Close();

dsdebug.debugWriteLine(projectData, projectData.DataSetName);
}
}
}
 
D

deko

The class you would create to implement the Singlton pattern is very
similar to a regular class. So stuff like the DataSet creation code
would still be handled by methods and properties within the class.

The crucial difference when using the Singlton pattern is in the class
constructor. When something tries to instantiate the class the class
contructor checks to see if it has already been instantiated. If not it
returns a new class object, however if it has been previously
instantiated it just returns a reference to the existing class object.

Hi and thanks for the reply. I beginning to get a handle on the concept of
a Singleton. Where I'm stuck is incorporating methods and properties into
Singleton. That code I posted pointed out a few areas of confusion that
still remain.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top