Custom Class - Different Instances

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hello,

I have a custom component class that I created that will basically save x
amount of "objects." Once x + 1 object pops in, the oldest one falls off.
It works great as I have it. In my test web page I create a Static object
and use the New to create a new instance of it. If I don't use the Static,
nothing is remembered. The only problem is, when I start a second page, I
expect it to have a NEW instance of the class but the numbers stored show up
the same.

How do I get it to always create a New instance. Am I missing the public,
private, protected, internal - modifiers in the wrong position?

Please help.


- - - - - - - Class File:
using System;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;

namespace NASQLStatements {
public class ThingsRemembered : System.ComponentModel.Component {
private System.ComponentModel.Container components = null;

private int iThingsToRemember;
protected internal ArrayList aThings;

public ThingsRemembered(System.ComponentModel.IContainer container) {
container.Add(this);
InitializeComponent();
aThings = new ArrayList(2);
}

public ThingsRemembered() {
InitializeComponent();
aThings = new ArrayList(2);
}

public ThingsRemembered(int iCapacity) {
InitializeComponent();
aThings = new ArrayList(iCapacity);
}

public ThingsRemembered(System.ComponentModel.IContainer container, int
iCapacity) {
container.Add(this);
InitializeComponent();
aThings = new ArrayList(iCapacity);
}

protected override void Dispose( bool disposing ) {
if( disposing ) {
if(components != null) {
components.Dispose();
}
}
base.Dispose( disposing );

iThingsToRemember = 0;
aThings.Clear(); // delete all items
aThings.TrimToSize(); // resize the array to system default

}

#region Component Designer generated code
private void InitializeComponent() {
components = new System.ComponentModel.Container();
}
#endregion

public int ThingsToRemember {
get { return iThingsToRemember; }
set {
iThingsToRemember = value;
aThings.Capacity = iThingsToRemember; // size the array
} // set
} // ThingsToRemember - Property - Read/Write

public bool AddAThing(object oThing) {
try {
if(aThings.Count == aThings.Capacity) {
aThings.RemoveAt(0); // remove the oldest one
} // if there are already the maximum number of items in the array
aThings.Add(oThing); // add the new one
return true;
} catch(Exception e) {
sLastError = e.ToString();
return false;
} // try-catch errors
} // AddAThing - Method

public string LastError {
get { return sLastError; }
} // LastError - Property - Read Only

public object LastThing() {
return aThings[aThings.Count - 1];
} // LastThing - Method

public object FirstThing() {
return aThings[0];
} // FirstThing - Method

public ArrayList AllThings {
get { return aThings; }
} // AllThings - Property - Read Only
}
}


- - - - - - - Test File:
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using NASQLStatements;

namespace TestThings {
public class WebForm1 : System.Web.UI.Page {

protected System.Web.UI.WebControls.Button cmndAddThing;
protected System.Web.UI.WebControls.Button cmndShowThings;
protected System.Web.UI.WebControls.Label lablThings;

private static NASQLStatements.ThingsRemembered oStuff = new
NASQLStatements.ThingsRemembered();

private void Page_Load(object sender, System.EventArgs e) {
if(!Page.IsPostBack) {
oStuff.ThingsToRemember = 5;
lablThings.Text = oStuff.AllThings.Capacity.ToString() +
"<br>" + oStuff.AllThings.Count.ToString();
} // if this is the first time to the page
}

#region Web Form Designer generated code
override protected void OnInit(EventArgs e) {
InitializeComponent();
base.OnInit(e);
}

private void InitializeComponent() {
this.cmndAddThing.Click += new
System.EventHandler(this.cmndAddThing_Click);
this.cmndShowThings.Click += new
System.EventHandler(this.cmndShowThings_Click);
this.cmndError.Click += new System.EventHandler(this.cmndError_Click);
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion

private void cmndShowThings_Click(object sender, System.EventArgs e) {
lablThings.Text = "" + oStuff.AllThings.Capacity.ToString() + "<br>";

for(int iPos = oStuff.AllThings.Count - 1; iPos >= 0; iPos--) {
lablThings.Text += oStuff.AllThings[iPos].ToString() + "<hr>";
} // for each item
}

private void cmndAddThing_Click(object sender, System.EventArgs e) {
Random rRandom = new Random(DateTime.Now.Millisecond);
int iValue = rRandom.Next(1, 1000);
lablThings.Text += "<br>" + oStuff.AddAThing(iValue).ToString();
}
}
}


As you can see, in the Test file I declare the Class as private static and
do a NEW. I assumed the New is necessary so it can create a New instance of
it. If it take out the Static modifier, nothing works and no random numbers
are stored. If I leave it in, it will remember the number (5) I have told
it. But so will each new web page I bring up and point to that page.

Please help.
 
You are getting the problem because you have a static instance. You need to
not use a static instance and somehow store the object between calls to the
page. One way to do this is to use the ViewState (although this is probably
not the most efficient way).

For example:
====================
private NASQLStatements.ThingsRemembered oStuff;

private void Page_Load(object sender, System.EventArgs e) {

if(Session["stuff"] != null)
{
oStuff = Viewstate["stuff"] as ThingsRemembered;
}

if(oStuff == null)
{
oStuff = new ThingsRemembered();
}

if(!Page.IsPostBack) {
oStuff.ThingsToRemember = 5;
lablThings.Text = oStuff.AllThings.Capacity.ToString() +
"<br>" + oStuff.AllThings.Count.ToString();
} // if this is the first time to the page
}
====================

Now, you need to subscribe to the Page Unload event and in the code put the
following:

private void Page_Load(object sender, System.EventArgs e)
{
Viewstate["stuff"] = oStuff;
}


This will solve your issue BUT it means that the object needs to be
serialiable AND it will be sent back to the client.

A better solution from an efficiency point of view would be to have a static
HashList of ThingsRemembered objects and for each call to a page that is not
a postback add a new ThingsRememberd object with to the hashlist and use
something like a Guid (System.Guid) as the key. Then, just store the guid in
the viewstate. You can then take that guid out, and find the ThingsRememberd
object in the static Hashlist by using that key. This does have it's problems
though.

--
Brian Delahunty
Ireland

http://briandela.com/blog

INDA SouthEast - http://southeast.developers.ie/ - The .NET usergroup I
started in the southeast of Ireland.


Grigs said:
Hello,

I have a custom component class that I created that will basically save x
amount of "objects." Once x + 1 object pops in, the oldest one falls off.
It works great as I have it. In my test web page I create a Static object
and use the New to create a new instance of it. If I don't use the Static,
nothing is remembered. The only problem is, when I start a second page, I
expect it to have a NEW instance of the class but the numbers stored show up
the same.

How do I get it to always create a New instance. Am I missing the public,
private, protected, internal - modifiers in the wrong position?

Please help.


- - - - - - - Class File:
using System;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;

namespace NASQLStatements {
public class ThingsRemembered : System.ComponentModel.Component {
private System.ComponentModel.Container components = null;

private int iThingsToRemember;
protected internal ArrayList aThings;

public ThingsRemembered(System.ComponentModel.IContainer container) {
container.Add(this);
InitializeComponent();
aThings = new ArrayList(2);
}

public ThingsRemembered() {
InitializeComponent();
aThings = new ArrayList(2);
}

public ThingsRemembered(int iCapacity) {
InitializeComponent();
aThings = new ArrayList(iCapacity);
}

public ThingsRemembered(System.ComponentModel.IContainer container, int
iCapacity) {
container.Add(this);
InitializeComponent();
aThings = new ArrayList(iCapacity);
}

protected override void Dispose( bool disposing ) {
if( disposing ) {
if(components != null) {
components.Dispose();
}
}
base.Dispose( disposing );

iThingsToRemember = 0;
aThings.Clear(); // delete all items
aThings.TrimToSize(); // resize the array to system default

}

#region Component Designer generated code
private void InitializeComponent() {
components = new System.ComponentModel.Container();
}
#endregion

public int ThingsToRemember {
get { return iThingsToRemember; }
set {
iThingsToRemember = value;
aThings.Capacity = iThingsToRemember; // size the array
} // set
} // ThingsToRemember - Property - Read/Write

public bool AddAThing(object oThing) {
try {
if(aThings.Count == aThings.Capacity) {
aThings.RemoveAt(0); // remove the oldest one
} // if there are already the maximum number of items in the array
aThings.Add(oThing); // add the new one
return true;
} catch(Exception e) {
sLastError = e.ToString();
return false;
} // try-catch errors
} // AddAThing - Method

public string LastError {
get { return sLastError; }
} // LastError - Property - Read Only

public object LastThing() {
return aThings[aThings.Count - 1];
} // LastThing - Method

public object FirstThing() {
return aThings[0];
} // FirstThing - Method

public ArrayList AllThings {
get { return aThings; }
} // AllThings - Property - Read Only
}
}


- - - - - - - Test File:
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using NASQLStatements;

namespace TestThings {
public class WebForm1 : System.Web.UI.Page {

protected System.Web.UI.WebControls.Button cmndAddThing;
protected System.Web.UI.WebControls.Button cmndShowThings;
protected System.Web.UI.WebControls.Label lablThings;

private static NASQLStatements.ThingsRemembered oStuff = new
NASQLStatements.ThingsRemembered();

private void Page_Load(object sender, System.EventArgs e) {
if(!Page.IsPostBack) {
oStuff.ThingsToRemember = 5;
lablThings.Text = oStuff.AllThings.Capacity.ToString() +
"<br>" + oStuff.AllThings.Count.ToString();
} // if this is the first time to the page
}

#region Web Form Designer generated code
override protected void OnInit(EventArgs e) {
InitializeComponent();
base.OnInit(e);
}

private void InitializeComponent() {
this.cmndAddThing.Click += new
System.EventHandler(this.cmndAddThing_Click);
this.cmndShowThings.Click += new
System.EventHandler(this.cmndShowThings_Click);
this.cmndError.Click += new System.EventHandler(this.cmndError_Click);
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion

private void cmndShowThings_Click(object sender, System.EventArgs e) {
lablThings.Text = "" + oStuff.AllThings.Capacity.ToString() + "<br>";

for(int iPos = oStuff.AllThings.Count - 1; iPos >= 0; iPos--) {
lablThings.Text += oStuff.AllThings[iPos].ToString() + "<hr>";
} // for each item
}

private void cmndAddThing_Click(object sender, System.EventArgs e) {
Random rRandom = new Random(DateTime.Now.Millisecond);
int iValue = rRandom.Next(1, 1000);
lablThings.Text += "<br>" + oStuff.AddAThing(iValue).ToString();
}
}
}


As you can see, in the Test file I declare the Class as private static and
do a NEW. I assumed the New is necessary so it can create a New instance of
it. If it take out the Static modifier, nothing works and no random numbers
are stored. If I leave it in, it will remember the number (5) I have told
it. But so will each new web page I bring up and point to that page.

Please help.
 
Thanks Brian,

I will look into the Hashlist here in a bit. This is the way I was
suggested to try from a different group and it works. Not sure if there is a
limit to Session variables. If it is like a cookie's limit, since it is a
cookie, then 4096 bytes. Here is the code...

when you do:
private static NASQLStatements.ThingsRemembered oStuff = new
NASQLStatements.ThingsRemembered();

you are saying that there's ever only 1 instance (amongst all threads (users
or requests)) of ThingsRemembered. That is, when user 1 and user 2 hit this
page, they are accessing the same instance. Think of it, if you will, as
having this stored in the Application variable. It's worse because it isn't
thread-safe.

If you remove the static, you'll now have 1 instance per thread (or per
request). This is likely closer to what you want...but not exactly what you
want. Everytime the same user hits the button, a new instance will be
created, meaning previous things this user added will be lost. In other
words, your instance will now have the lifetime of a single request - my
guess is that's also not what you want. What you want is something in
between, it's "static" per user. To achieve this you need to store the
instance somewhere, such as the Session variable. So what you could do is:

private NASQLStatements.ThingsRemembered oStuff;

public void page_init(...) {
oStuff = (NASQLStatements.ThingsRemembered) Session["ThingsToRemember"];
if (oStuff == null) //it'll be null the first time
{
oStuff = new NASQLStatements.ThingsRemembered();
Session.Add("ThingsToRemember", oStuff);
}
}


Thanx,
Grigs


Brian Delahunty said:
You are getting the problem because you have a static instance. You need to
not use a static instance and somehow store the object between calls to the
page. One way to do this is to use the ViewState (although this is probably
not the most efficient way).

For example:
====================
private NASQLStatements.ThingsRemembered oStuff;

private void Page_Load(object sender, System.EventArgs e) {

if(Session["stuff"] != null)
{
oStuff = Viewstate["stuff"] as ThingsRemembered;
}

if(oStuff == null)
{
oStuff = new ThingsRemembered();
}

if(!Page.IsPostBack) {
oStuff.ThingsToRemember = 5;
lablThings.Text = oStuff.AllThings.Capacity.ToString() +
"<br>" + oStuff.AllThings.Count.ToString();
} // if this is the first time to the page
}
====================

Now, you need to subscribe to the Page Unload event and in the code put the
following:

private void Page_Load(object sender, System.EventArgs e)
{
Viewstate["stuff"] = oStuff;
}


This will solve your issue BUT it means that the object needs to be
serialiable AND it will be sent back to the client.

A better solution from an efficiency point of view would be to have a static
HashList of ThingsRemembered objects and for each call to a page that is not
a postback add a new ThingsRememberd object with to the hashlist and use
something like a Guid (System.Guid) as the key. Then, just store the guid in
the viewstate. You can then take that guid out, and find the ThingsRememberd
object in the static Hashlist by using that key. This does have it's problems
though.

--
Brian Delahunty
Ireland

http://briandela.com/blog

INDA SouthEast - http://southeast.developers.ie/ - The .NET usergroup I
started in the southeast of Ireland.


Grigs said:
Hello,

I have a custom component class that I created that will basically save x
amount of "objects." Once x + 1 object pops in, the oldest one falls off.
It works great as I have it. In my test web page I create a Static object
and use the New to create a new instance of it. If I don't use the Static,
nothing is remembered. The only problem is, when I start a second page, I
expect it to have a NEW instance of the class but the numbers stored show up
the same.

How do I get it to always create a New instance. Am I missing the public,
private, protected, internal - modifiers in the wrong position?

Please help.


- - - - - - - Class File:
using System;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;

namespace NASQLStatements {
public class ThingsRemembered : System.ComponentModel.Component {
private System.ComponentModel.Container components = null;

private int iThingsToRemember;
protected internal ArrayList aThings;

public ThingsRemembered(System.ComponentModel.IContainer container) {
container.Add(this);
InitializeComponent();
aThings = new ArrayList(2);
}

public ThingsRemembered() {
InitializeComponent();
aThings = new ArrayList(2);
}

public ThingsRemembered(int iCapacity) {
InitializeComponent();
aThings = new ArrayList(iCapacity);
}

public ThingsRemembered(System.ComponentModel.IContainer container, int
iCapacity) {
container.Add(this);
InitializeComponent();
aThings = new ArrayList(iCapacity);
}

protected override void Dispose( bool disposing ) {
if( disposing ) {
if(components != null) {
components.Dispose();
}
}
base.Dispose( disposing );

iThingsToRemember = 0;
aThings.Clear(); // delete all items
aThings.TrimToSize(); // resize the array to system default

}

#region Component Designer generated code
private void InitializeComponent() {
components = new System.ComponentModel.Container();
}
#endregion

public int ThingsToRemember {
get { return iThingsToRemember; }
set {
iThingsToRemember = value;
aThings.Capacity = iThingsToRemember; // size the array
} // set
} // ThingsToRemember - Property - Read/Write

public bool AddAThing(object oThing) {
try {
if(aThings.Count == aThings.Capacity) {
aThings.RemoveAt(0); // remove the oldest one
} // if there are already the maximum number of items in the array
aThings.Add(oThing); // add the new one
return true;
} catch(Exception e) {
sLastError = e.ToString();
return false;
} // try-catch errors
} // AddAThing - Method

public string LastError {
get { return sLastError; }
} // LastError - Property - Read Only

public object LastThing() {
return aThings[aThings.Count - 1];
} // LastThing - Method

public object FirstThing() {
return aThings[0];
} // FirstThing - Method

public ArrayList AllThings {
get { return aThings; }
} // AllThings - Property - Read Only
}
}


- - - - - - - Test File:
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using NASQLStatements;

namespace TestThings {
public class WebForm1 : System.Web.UI.Page {

protected System.Web.UI.WebControls.Button cmndAddThing;
protected System.Web.UI.WebControls.Button cmndShowThings;
protected System.Web.UI.WebControls.Label lablThings;

private static NASQLStatements.ThingsRemembered oStuff = new
NASQLStatements.ThingsRemembered();

private void Page_Load(object sender, System.EventArgs e) {
if(!Page.IsPostBack) {
oStuff.ThingsToRemember = 5;
lablThings.Text = oStuff.AllThings.Capacity.ToString() +
"<br>" + oStuff.AllThings.Count.ToString();
} // if this is the first time to the page
}

#region Web Form Designer generated code
override protected void OnInit(EventArgs e) {
InitializeComponent();
base.OnInit(e);
}

private void InitializeComponent() {
this.cmndAddThing.Click += new
System.EventHandler(this.cmndAddThing_Click);
this.cmndShowThings.Click += new
System.EventHandler(this.cmndShowThings_Click);
this.cmndError.Click += new System.EventHandler(this.cmndError_Click);
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion

private void cmndShowThings_Click(object sender, System.EventArgs e) {
lablThings.Text = "" + oStuff.AllThings.Capacity.ToString() + "<br>";

for(int iPos = oStuff.AllThings.Count - 1; iPos >= 0; iPos--) {
lablThings.Text += oStuff.AllThings[iPos].ToString() + "<hr>";
} // for each item
}

private void cmndAddThing_Click(object sender, System.EventArgs e) {
Random rRandom = new Random(DateTime.Now.Millisecond);
int iValue = rRandom.Next(1, 1000);
lablThings.Text += "<br>" + oStuff.AddAThing(iValue).ToString();
}
}
}


As you can see, in the Test file I declare the Class as private static and
do a NEW. I assumed the New is necessary so it can create a New instance of
it. If it take out the Static modifier, nothing works and no random numbers
are stored. If I leave it in, it will remember the number (5) I have told
it. But so will each new web page I bring up and point to that page.

Please help.
 
Back
Top