How to encapsulate state variables in NModel? - c#

I have a model program that represents message flow along a chain of servers:
public class MyModel
{
static bool x_send_msg1 = false; // has X sent msg1?
static bool y_recv_msg1 = false; // has Y received msg1?
static bool y_send_msg1 = false; // has Y sent msg1?
static bool z_send_msg1 = false; // has Z received msg1?
// (etc for more servers and more messages)
[Action]
static void YSendMsg1()
{
// Y sends Msg1 to Z
y_send_msg1 = true;
z_recv_msg1 = true;
}
static bool YSendMsg1Enabled()
{
// in the simplest case, this can happen whenever Y has received the
// message but not yet forwarded it
return y_recv_msg1 && !y_send_msg1;
}
}
There are lots more messages. The Enabled() logic for each server and message type is slightly different, but the state is similar, so I would like to encapsulate it by writing something more like:
class State
{
public bool send_msg1 = false;
public bool recv_msg1 = false;
}
public static State X = new State();
public static State Y = new State();
and then use the encapsulated state in my actions:
[Action]
static void YSendMsg1()
{
// instead of y_qqq above, now we can write Y.qqq:
Y.send_msg1 = true;
Z.recv_msg1 = true;
}
static bool YSendMsg1Enabled()
{
return Y.recv_msg1 && !Y.send_msg1;
}
However NModel won't let me use objects in this fashion to hold my state. Is there some other way I can avoid defining repeating groups of booleans, one for each server in the chain?

Questions of style aside, the main benefit of encapsulating the state as shown in the question is to reduce the amount of code that must be written and read. Instead of having to write (#servers * #messages) declarations, only (#server + #messages) are required.
The same reduction in code (with corresponding improvements in readability and reduction in carpal tunnel syndrome) can be achieved by using NModel's built-in Set class to track the state of each message. A set called send_msg1 contains the names of all the servers that have sent msg1:
public class MyModel
{
static set<int> send_msg1 = set<int>.EmptySet; // has server #n sent msg #1?
static set<int> recv_msg1 = set<int>.EmptySet; // has server #n received msg #1?
// (etc for more messages)
static int X = 1;
static int Y = 2;
// (etc for more server names)
[Action]
static void YSendMsg1()
{
// Y sends Msg1 to Z
send_msg1 = send_msg1.Add(Y);
recv_msg1 = recv_msg1.Add(Z);
}
static bool YSendMsg1Enabled()
{
// in the simplest case, this can happen whenever Y has received the
// message but not yet forwarded it
return recv_msg1.Contains(Y) && !send_msg1.Contains(Y);
}
}
(It is possible to reduce the amount of code event further, for example by using a map of sets to hold everything in a single variable. However one advantage of leaving the state patially separated is that it produces more legible state summaries in the model viewer.)

Since writing my answer above, I have learned of another solution that is closer to what I was originally looking for.
To use objects with instance variables, you can derive from LabeledInstance as shown below. The instances should be allocated using the static Create() method, and fields should be initialized in an overridden Initialize() method.
(You can also use instance methods for actions, but to do so you must assign a domain to the class; the name of that domain should correspond to a static set that contains all current instances of the class.)
Behind the scenes, NModel is going to translate this class into a bunch of maps, one for each instance variable in the class. The key into those maps will be indexed instances of the class name, e.g. State(1). This can be somewhat hard to read within the MVC tool, so you may also want to keep some kind of instance variable that contains a legible, consolidated summary of the object's state.
class State : LabeledInstance<State>
{
public override void Initialize()
{
send_msg1 = false;
recv_msg1 = false;
}
public bool send_msg1;
public bool recv_msg1;
}
public static State X = State.Create();
public static State Y = State.Create();

I think the observer pattern might help you here - http://www.dofactory.com/Patterns/PatternObserver.aspx

Related

Values fetched from database and assigned to variables do not persist across layers

I have a class like this and the purpose is to set these Boolean values in the data layer with purpose of persisting these values in through out application's life cycle.
public class ProjectFeatureIndicatorMetadata
{
public bool? SprcCustomIncludesInd;
public bool? SprcCustomVariablesInd;
public bool? SprcRatingFlowInd;
public bool? SprcFactorSetsGenerationInd;
public static void SetFeatureIndicatorValues(string name, bool value)
{
ProjectFeatureIndicatorMetadata indicators = new Data.ProjectFeatureIndicatorMetadata();
if(name == "SprcCustomIncludesInd") { indicators.SprcCustomIncludesInd = value; }
if(name == "SprcCustomVariablesInd") { indicators.SprcCustomVariablesInd = value; }
if(name == "SprcRatingFlowInd") { indicators.SprcRatingFlowInd = value; }
if(name == "SprcFactorSetsGenerationInd") { indicators.SprcFactorSetsGenerationInd = value; }
}
}
Then I have the data layer, pretty straight forward. I can confirm that database call is made and values are being fetched and at this level, the indicators are assigned values:
public void GetCachedProjectFeatureIndicatorsStatus(ProjectIdentifier projectId)
{
ProjectFeatureIndicatorMetadata indicatorData = new ProjectFeatureIndicatorMetadata();
GetSpHelper().ExecuteReader(
spName: "ITV.usp_ProjectFeatureIndicators_GetByProjectId",
parmsDg: parms => parms.AddWithValue("#ProjectId", projectId.Guid),
methodDg: reader =>
{
while (reader.Read())
{
ProjectFeatureIndicatorMetadata.SetFeatureIndicatorValues(
"SprcCustomVariablesInd", reader.Column<bool>("SprcCustomVariablesInd"));
ProjectFeatureIndicatorMetadata.SetFeatureIndicatorValues(
"SprcRatingFlowInd", reader.Column<bool>("SprcRatingFlowInd"));
ProjectFeatureIndicatorMetadata.SetFeatureIndicatorValues(
"SprcFactorSetsGenerationInd", reader.Column<bool>("SprcFactorSetsGenerationInd"));
ProjectFeatureIndicatorMetadata.SetFeatureIndicatorValues(
"SprcCustomIncludesInd", reader.Column<bool>("SprcCustomIncludesInd"));
}
return true;
});
}
The application start up class calls middle layer through an interface. Below is hot it's implemented. The four 'vars' are just a test code but the bottom line is, values for the indicator variables are null. And I don't know why.
Data.GetCachedProjectFeatureIndicatorStatus(project);
ProjectFeatureIndicatorMetadata indicators = new ProjectFeatureIndicatorMetadata();
var sprcCustomIncludesInd = indicators.SprcCustomIncludesInd;
var sprcCustomVariablesInd = indicators.SprcCustomVariablesInd;
var sprcFactorSetsGenerationInd = indicators.SprcFactorSetsGenerationInd;
var sprcRatingFlowInd = indicators.SprcRatingFlowInd;
The Data object is class variable in the start up class:
private ProjectData Data
{
[Pure, DebuggerStepThrough]
get { return ProjectDataProvider.ProjectData; }
}
ProjectData is large class that holds lot of other stuff but my code only has this call to the interface:
public void GetCachedProjectFeatureIndicatorStatus(ProjectIdentifier projectId)
{
_server.GetCachedProjectFeatureIndicatorStatus(projectId);
}
Then another class that has the following method that is the main logic for this task:
public void GetCachedProjectFeatureIndicatorStatus(ProjectIdentifier projectId)
{
ProjectFeatureIndicatorMetadata indicators = new ProjectFeatureIndicatorMetadata();
using (new WriteLock(_lock))
{
if (indicators.SprcCustomIncludesInd != null ||
indicators.SprcCustomVariablesInd != null ||
indicators.SprcFactorSetsGenerationInd != null ||
indicators.SprcRatingFlowInd != null)
{
return;
}
else
{
GetProjectFeatureIndicatorsStatus(projectId);
return;
}
}
}
public virtual void GetProjectFeatureIndicatorsStatus(Guid projectId)
{
string PROJECT_SERVER_SQL_CONNECTION_STRING = ConfigurationManager.ConnectionStrings["ConfigConnectionString"].ConnectionString;
var configConnectionFactory = new ManualConnectionFactory(PROJECT_SERVER_SQL_CONNECTION_STRING);
var projectFeatureIndicatorTable = new ProjectFeatureIndicatorsTable(configConnectionFactory);
projectFeatureIndicatorTable.GetCachedProjectFeatureIndicatorsStatus(projectId);
}
I don't fully understand some of your code, like why in your method that has a DataReader, you make a new object instance of ProjectFeatureIndicatorMetaData but then you start looping the reader and make a bunch of static calls like:
while (reader.Read())
{
ProjectFeatureIndicatorMetadata.SetFeatureIndicatorValues(
"SprcCustomVariablesInd", reader.Column<bool>("SprcCustomVariablesInd"));
This won't do anything with the instance you just made, and you don't appear to access the static again outside the data reading loop, nor do you return the instance you made - you instead make another new instance in a different method and then try to access its properties (which will be null)
ProjectFeatureIndicatorMetadata indicators = new ProjectFeatureIndicatorMetadata();
using (new WriteLock(_lock))
{
if (indicators.SprcCustomIncludesInd != null ||
Ultimately if you want your data to travel round your app you have to make an instance, fill it with data and then pass it somewhere (call a method and pass it as a parameter/return it from a method to a method that captures the return value). Right now you have some static things, some non static things and whenever you want to do anything you make a new instance, fill it with data and then immediately throw it away, or you make a new instance and try to read from it as though you expect it to contain data. It's like you expect statics to be some sort of defaulting mechanism that, once called, mean that every new instance you make of that type gets the "defaults" that were set by calling the static methods - statics aren't like that. Statics are more like "there is one instance of the static stuff, that the runtime makes for you, but to access it you must always use it in a static way(no instance variables, just the type name)" - you're mixing "new" (==make a new instance) with static(==a single already existing instance the runtime made)
I'd generally advise to stay away from statics as a way of passing data around; as global variables they're almost always a bad idea in potentially concurrent situations. If you're setting up a cache of commonly used data at startup they may make sense but it introduces a high level of coupling to your classes; every class becomes dependent on the static and has to know what it is and cannot function without it. If you code in a more Dependency Injection style where you give every class instance the data it needs to function when you construct it, you don't get to a place where all classes depend on one - instead they use the data they're given and it isn't mandated how it gets it - you can use that class in a future project just by dropping it in and providing the same initial data from a different way

How to make whole POD object read and update operations lockfree?

Say we have a POD type:
private class Messages {
public byte[] last;
public byte[] next;
}
and its instance messages.
When a user (caller) requests instance we want to give him deep copy of messages object (that can be not the latest). When a user sets his own version we want to provide it to others as sun as possible yet not interrupting read requests (older version should be removed, not interrupting reads as soon as possible).
How to do such object versioning using System.Collections.Concurrent?
What have I tried:
internal class CuncurrentMessagesHelper {
private readonly ConcurrentStack<Messages> _stack = new ConcurrentStack<Messages>();
public CuncurrentMessagesHelper() {
}
public void SetLatest(Messages m) {
var length = _stack.Count;
_stack.Push(m);
var range = new Messages[length];
_stack.TryPopRange(range, 0, length);
}
public bool ReadLatest(out Messages result) {
return _stack.TryPeek(out result);
}
}
Yet such helper approach seems as ugly hack.
because even we know result is garanteed we use try and return bool instead of object;
it TryPopRange makes us create addintional array with size of all previous versions.
This isn't POD. It's a POCO. I suggest you read up on the difference between .NET's value types and reference types, since their semantics are crucial while writing safe concurrent code.
Since C# references are guaranteed to be atomic, the solution is simple (and doesn't require any special concurrent containers).
Assuming your Messages object is immutable once passed in:
internal class ConcurrentMessagesHelper {
private volatile Messages _current;
public void SetLatest(Messages m) {
_current = m;
}
public Messages ReadLatest() {
return _current;
}
}
Note that it's the reference to the object that's being copied here (atomically), and not the object's byte[] fields. volatile is required since the reference is accessed by multiple threads (it ensures correct behaviour, in particular with regards to memory ordering and limiting the optimizations the JIT can perform to only thread-safe ones).
If the Messages object passed to SetLatest can change while it's the latest, then all you have to do is make a copy first. SetLatest becomes:
public void SetLatest(Messages m) {
_current = DeepClone(m);
}
If readers are allowed to change the Messages object returned, then you have to copy it before letting them have it too. ReadLatest becomes:
public Messages ReadLatest() {
return DeepClone(_current);
}
Note that if the values contained in the byte[] fields of Messages are immutable during each message's lifetime, all you need is a shallow copy, not a deep one.
You can make the interface even nicer by wrapping it in a simple property:
internal class ConcurrentMessagesHelper {
private volatile Messages _current;
public Messages Current {
get { return DeepClone(_current); }
set { _current = DeepClone(value); }
}
private static Messages DeepClone(Messages m)
{
if (m == null)
return null;
return new Messages {
last = m.last == null ? null : (byte[])m.last.Clone(),
next = m.next == null ? null : (byte[])m.next.Clone()
};
}
}
If you actually did have a POD type (e.g. struct Messages), then I suggest the simplest solution would be to wrap it in a class so you can have an atomic reference to a copy of it, which would allow you to use the solution above. StrongBox<T> comes to mind.
The code in such a case becomes even simpler, because no explicit copying is required:
private struct Messages {
public byte[] last;
public byte[] next;
}
internal class ConcurrentMessagesHelper {
private volatile StrongBox<Messages> _current;
public Messages Current {
get { return _current.Value; }
set { _current = new StrongBox<Messages>(value); }
}
}
If the byte arrays in Messages can change during the object's lifetime, then we still need the deep cloning, though:
internal class ConcurrentMessagesHelper {
private volatile StrongBox<Messages> _current;
public Messages Current {
get { return DeepClone(_current.Value); }
set { _current = new StrongBox<Messages>(DeepClone(value)); }
}
private static Messages DeepClone(Messages m)
{
return new Messages {
last = m.last == null ? null : (byte[])m.last.Clone(),
next = m.next == null ? null : (byte[])m.next.Clone()
};
}
}

C# Private member shared by all class instances

I am currently working with C# using the Unity3D engine and have come upon the following problem:
I created a class that has two private references to instances of another class which it has to access. Once I create multiple instances of the class and set the references I found out that all instances were using the same variable. I realized this as I was destroying an instance and just before that set the two variables holding the references to null. Immediately after doing that all other instances were throwing NullReferenceExceptions because they were still trying to access the references. The referenced objects are fine, other scripts can still access them.
Here is some pseudo code illustrating the structure:
public class Character
{
// Character data
}
public class StatusEffect
{
private Character target;
private Character originator;
public void Init(Character _Target, Character _Originator)
{
target = _Target;
originator = _Originator;
}
public void Destroy()
{
target = null;
originator = null;
}
}
In the program it would be called like this:
StatusEffect effect = new StatusEffect();
effect.Init(player1, player2);
// Time goes by
effect.Destroy();
After calling Destroy() every StatusEffect's two references will be null.
This is not only an issue when destroying StatusEffects, but also when creating new ones. As soon as I touch the references from within a new instance all StatusEffects will reference the two Characters specified by the new StatusEffect.
I do not understand why or how I can fix this issue. Can someone enlighten me on this matter?
Cheers,
Valtaroth
EDIT:
Here is the real code as requested:
I have a container class holding several StatusEffects. As soon as it starts, it initializes all of them.
public class CElementTag
{
// ..Other data..
public float f_Duration; // Set in the editor
private CGladiator gl_target;
private CGladiator gl_originator;
private float f_currentDuration;
public CStatusEffect[] ar_statusEffects;
// Starts the effect of the element tag
public void StartEffect(CGladiator _Originator, CGladiator _Target)
{
gl_originator = _Originator;
gl_target = _Target;
f_currentDuration = f_Duration;
for(int i = 0; i < ar_statusEffects.Length; i++)
ar_statusEffects[i].Initialize(gl_originator, gl_target);
}
// Ends the effect of the element tag
public void EndEffect()
{
for(int i = 0; i < ar_statusEffects.Length; i++)
{
if(ar_statusEffects[i] != null)
ar_statusEffects[i].Destroy();
}
}
// Called every update, returns true if the tag can be destroyed
public bool ActivateEffect()
{
f_currentDuration -= Time.deltaTime;
if(f_currentDuration <= 0.0f)
{
EndEffect();
return true;
}
for(int i = 0; i < ar_statusEffects.Length; i++)
{
if(ar_statusEffects[i] != null && ar_statusEffects[i].Update())
RemoveStatusEffect(i);
}
return false;
}
// Removes expired status effects
private void RemoveStatusEffect(int _Index)
{
// Call destroy method
ar_statusEffects[_Index].Destroy();
// Remove effect from array
for(int i = _Index; i < ar_statusEffects.Length - 1; i++)
ar_statusEffects[i] = ar_statusEffects[i+1];
ar_statusEffects[ar_statusEffects.Length - 1] = null;
}
}
The actual StatusEffect class is holding the two references as well as some other data it needs to work. It has virtual methods because there are some classes inheriting from it.
public class CStatusEffect
{
// ..Necessary data..
// References
protected CGladiator gl_target;
protected CGladiator gl_originator;
virtual public void Initialize(CGladiator _Target, CGladiator _Originator)
{
gl_target = _Target;
gl_originator = _Originator;
// ..Initialize other necessary stuff..
}
virtual public void Destroy()
{
gl_target = null;
gl_originator = null;
// ..Tidy up other data..
}
virtual public bool Update()
{
// ..Modifying data of gl_target and gl_originator..
// Returns true as soon as the effect is supposed to end.
}
}
That should be all the relevant code concerning this problem.
EDIT2
#KeithPayne I have a static array of ElementTags defined in the editor and saved to xml. At the beginning of the program the static array is loading the xml and stores all element tags. When creating a new element tag to use I utilize this constructor:
// Receives a static tag as parameter
public CElementTag(CElementTag _Tag)
{
i_ID = _Tag.i_ID;
str_Name = _Tag.str_Name;
enum_Type = _Tag.enum_Type;
f_Duration = _Tag.f_Duration;
ar_statusEffects = new CStatusEffect[_Tag.ar_statusEffects.Length];
Array.Copy(_Tag.ar_statusEffects, ar_statusEffects, _Tag.ar_statusEffects.Length);
}
Do I have to use a different method to copy the array to the new tag? I thought Array.Copy would make a deep copy of the source array and stored it in the destination array. If it is in fact making a shallow copy, I understand where the problem is coming from now.
From Array.Copy Method (Array, Array, Int32):
If sourceArray and destinationArray are both reference-type arrays or
are both arrays of type Object, a shallow copy is performed. A shallow
copy of an Array is a new Array containing references to the same
elements as the original Array. The elements themselves or anything
referenced by the elements are not copied. In contrast, a deep copy of
an Array copies the elements and everything directly or indirectly
referenced by the elements.
Consider this fluent version of the StatusEffect class and its usage below:
public class StatusEffect
{
public Character Target { get; private set; }
public Character Originator { get; private set; }
public StatusEffect Init(Character target, Character originator)
{
Target = target.Clone()
Originator = originator.Clone();
return this;
}
//...
}
public CElementTag(CElementTag _Tag)
{
i_ID = _Tag.i_ID;
str_Name = _Tag.str_Name;
enum_Type = _Tag.enum_Type;
f_Duration = _Tag.f_Duration;
ar_statusEffects = _Tag.ar_statusEffects.Select(eff =>
new StatusEffect().Init(eff.Target, eff.Originator)).ToArray();
// ar_statusEffects = new CStatusEffect[_Tag.ar_statusEffects.Length];
// Array.Copy(_Tag.ar_statusEffects, ar_statusEffects, _Tag.ar_statusEffects.Length);
}
Because you're passing in references to the objects via your Init() method, you're not actually "copying" the objects, just maintaining a reference to the same underlying objects in memory.
If you have multiple players with the same references to the same underlying objects, then changes made by player 1 will effect the objects being used by player 2.
Having said all that, you're not actually disposing the objects in your Destory method. Just setting the local instance references to Null which shouldn't affect any other instances of StatusEffects. Are you sure something else isn't disposing the objects, or that you haven't properly init'd your other instances.
If you do want to take a full copy of the passed in objects, take a look at the ICloneable interface. It looks like you want to pass in a copy of the objects into each Player.
public class Character : ICloneable
{
// Character data
//Implement Clone Method
}
public class StatusEffect
{
private Character target;
private Character originator;
public void Init(Character _Target, Character _Originator)
{
target = _Target.Clone()
originator = _Originator.Clone();
}
The fields aren't shared(static) among other instances. So calling target = null; in Destroy() won't affect other instances.
StatusEffect effect1 = new StatusEffect();
effect1.Init(player1, player2);
StatusEffect effect2 = new StatusEffect();
effect2.Init(player1, player2);
// Time goes by
effect2.Destroy();
// Some more time goes by
// accessing effect1.target won't give a `NullReferenceException` here unless player1 was null before passed to the init.
effect1.Destroy();
I think you did forget the Init(..) on the other instances. Every time you create an instance of StatusEffect, you need to call Init(...).
Update:
This line will clear the reference to the effect, but you never recreate it:
ar_statusEffects[ar_statusEffects.Length - 1] = null;
so the next time you call ar_statusEffects[x].Update() or Initialize() etc it will throw a NullReferenceException
If you want to clear out effects within you array, you could create an Enable bool in the effect, this way you only have to set/reset it.
for(int i = 0; i < ar_statusEffects.Length; i++)
if(ar_statusEffects[i].IsEnabled)
ar_statusEffects[i].Update();
Why don't you use a List instead? Arrays will be faster as long you don't have to shuffle in it. (like circulair buffers etc)
Thanks to Keith Payne I figured out where the problem was. I was creating a deep copy of CElementTag, but not of my ar_statusEffects array. I wrongly assumed Array.Copy was creating a deep copy of an array when it actually was not.
I implemented the IClonable interface for my CStatusEffect and use the Clone() method to create a true deep copy for each member of the static array and add it to the new tags ar_statusEffects array. This way I have seperate instances of the effects instead of references to the same static effect.
Thanks to everyone, especially Keith Payne, for their help and support!

How can I access a member from another class with a Timer?

I'm currently writing a class to calculate the average download speed over a defined period of time, taking a defined number of samples. The way I thought this would work is that this class runs a Timer object, which calls a method inside said class that will look at the bytes downloaded (maintained in a parent class, the FTPDownloadFile), and then store that sample in a Queue. My issue is accessing the number of bytes downloaded, however.
My method of accessing that information was through a reference that was passed in when the download calculating class was constructed, however, it seems like I'm not understanding/using references correctly. The variable that is passed in always appears to be 0, even though I can see the original variable changing.
Can anyone tell me what I'm doing wrong / suggest a better way for me to accomplish what I want to do?
First, here is the class that is handling the calculation of the download speed:
public class SpeedCalculator
{
private const int samples = 5;
private const int sampleRate = 1000; //In milliseconds
private int bytesDownloadedSinceLastQuery;
private System.Threading.Timer queryTimer;
private Queue<int> byteDeltas = new Queue<int>(samples);
private int _bytesDownloaded;
public SpeedCalculator(ref int bytesDownloaded)
{
_bytesDownloaded = bytesDownloaded;
}
public void StartPolling()
{
queryTimer = new System.Threading.Timer(this.QueryByteDelta, null, 0, sampleRate);
}
private void QueryByteDelta(object data)
{
if (byteDeltas.Count == samples)
{
byteDeltas.Dequeue();
}
byteDeltas.Enqueue(_bytesDownloaded - bytesDownloadedSinceLastQuery);
bytesDownloadedSinceLastQuery = _bytesDownloaded;
}
/// <summary>
/// Calculates the average download speed over a predefined sample size.
/// </summary>
/// <returns>The average speed in bytes per second.</returns>
public float GetDownloadSpeed()
{
float speed;
try
{
speed = (float)byteDeltas.Average() / ((float)sampleRate / 1000f);
}
catch {speed = 0f;}
return speed;
}
That class is contained inside of my FTPDownloadFile class:
class FTPDownloadFile : IDisposable
{
private const int recvBufferSize = 2048;
public int bytesDownloaded;
public SpeedCalculator Speed;
private FileStream localFileStream;
FtpWebResponse ftpResponse;
Stream ftpStream;
FtpWebRequest ftpRequest;
public List<string> log = new List<string>();
private FileInfo destFile;
public event EventHandler ConnectionEstablished;
public FTPDownloadFile()
{
bytesDownloaded = 0;
Speed = new SpeedCalculator(ref bytesDownloaded);
}
public void GetFile(string host, string remoteFile, string user, string pass, string localFile)
{
//Some code to start the download...
Speed.StartPolling();
}
public class SpeedCalculator {...}
}
This is a common 'issue' with understanding 'ref' parameters in C#. You see, unlike C+, there are no real value references in C#.
In C++, when you pass-by-reference, you actually internally pass pointer to the variable. Therefore, you can have a class member variable of type "int&" that is actual reference to an integer stored elsewhere.
In C#, 'ref' or 'out' parameter works in a similar way, but noone talks about pointers. You cannot store the reference. You cannot have a 'ref' class member. Look at your class: the sotrage variable is of type 'int', plain 'int', not a reference.
You actually are passing that value by-ref, but then you copy it to the member variable. The 'reference' is gone at the point where your constructor ends.
To walk it around, you have to keep the actual source object, and either introduce a strong dependency, or a weak one by an interface, or do it lazy/functional way - by a delegate
Ex#1: strong reference
public class SpeedCalculator
{
private const int samples = 5;
private const int sampleRate = 1000; //In milliseconds
private int bytesDownloadedSinceLastQuery;
private System.Threading.Timer queryTimer;
private Queue<int> byteDeltas = new Queue<int>(samples);
private FTPDownloadFile downloader; // CHANGE
public SpeedCalculator(FTPDownloadFile fileDownloader) // CHANGE
{
downloader = fileDownloader;
}
public void StartPolling()
{
queryTimer = new System.Threading.Timer(this.QueryByteDelta, null, 0, sampleRate);
}
private void QueryByteDelta(object data)
{
if (byteDeltas.Count == samples)
{
byteDeltas.Dequeue();
}
byteDeltas.Enqueue(_bytesDownloaded - bytesDownloadedSinceLastQuery);
bytesDownloadedSinceLastQuery = downloader.bytesDownloaded; // CHANGE
}
//and in the other file
public FTPDownloadFile()
{
bytesDownloaded = 0;
Speed = new SpeedCalculator( this ); // CHANGE
}
In C#, every object (class MyObject) is passed by reference, or implicit pointer, therefore taking FTPDownloadFile by parameter and assigning it to a member variable does not copy it, it is truly passed by ref (on the other hand, values (int, decimal, ..) and structs (struct MyThing) are always passed by value, so your original _bytes = bytes made a copy of int). Hence, later, I can just query the
Ex#2: "weak" reference
public interface IByteCountSource
{
int BytesDownloaded {get;}
}
public class FTPDownloadFile : IDisposable, IByteCountSource
{
.....
public int BytesDownloaded { get { return bytesDownloaded; } }
.....
public FTPDownloadFile()
{
bytesDownloaded = 0;
Speed = new SpeedCalculator( this ); // note no change versus Ex#1 !
}
}
public class SpeedCalculator
{
....
private IByteCountSource bts;
public SpeedCalculator(IByteCountSource countSource) // no "FTP" information!
{
this.bts = countSource;
}
...
private void QueryByteDelta(object data)
{
....
bytesDownloadedSinceLastQuery = bts.BytesDownloaded;
}
The first example was quick and dirty. In general, we usually want the classes to know as least as possible about all other. So why should the SpeedCalculator know about the FTPDownloadFile? All it needs to know is the current byte-count. So I introduced an interface to 'hide' the actual source behind. Now the SpeedCalculator can take the value from any object that implements the interface - be it FTPDownloadFile, HTTPDownloadFile or some DummyTestDownloader
Ex#3: delegates, anonymous functions, etc
public class SpeedCalculator
{
....
private Func<int> bts;
public SpeedCalculator(Func<int> countSource)
{
this.bts = countSource;
}
...
private void QueryByteDelta(object data)
{
....
bytesDownloadedSinceLastQuery = bts();
}
// and in the other file
private int getbytes() { return bytesDownloaded; }
public FTPDownloadFile()
{
bytesDownloaded = 0;
Speed = new SpeedCalculator( this.getbytes ); // note it is NOT a getbytes() !
}
// or even
public FTPDownloadFile()
{
bytesDownloaded = 0;
Speed = new SpeedCalculator( () => this.bytesDownloaded ); // CHANGE
}
The example with an interface is pretty, but the interface was 'small'. One is ok, but sometimes you'd need to introduce dozens of such one-property or one-method interfaces, it gets somewhat boring and cluttering. Especially if all of that is 'internal implementation' that anyways isn't published for any other people to use. You can very easily drop such small interface with a short lambda, as in the third example. Instead of receiving and storing a object-that-implememts-an-interface, I changed the parameter to Func. This way I require to get "a method that returns an INT". Them, I pass the some method. Note that during new SpeedCalculator, I do not call the this.getbytes(), I pass the method without parenthesis - this causes the method to be wrapped into Func delegate, that will be later invoked as bts(), and will return current counter. This getbytes is rarely used, only in this one place - so I can even drop it completely and write anonymous function right at the point of constructor call, as you can see in the "or even" part.
However, I'd suggest you to stick with interfaces for now, they are much clearer to read and understand.

Static class remaining in memory.....how best to achieve this

I've created a very simple helper class that I can use in my ASP.Net pages. The idea is that it is supposed to be a very simple way to log an on-page error or success (not a form validation error) and then display it to the user.
In my public helper class I have a class which has certain properties, as shown below:
public class UserMessage
{
public UserMessage()
{
Messages = new Dictionary<string, string>();
}
public string SummaryMessage;
public Dictionary<string, string> Messages;
public bool ShowMessages;
public bool ShowAsError;
}
I then have a variable which is used to store an instance of the UserMessage class, like so:
private static UserMessage _userMessage { get; set; }
I then have two public static methods, one to log a message, the other to display all the messages, like so:
public static void LogSummary(string summaryMessage, bool showIndividualMessages, bool showAsError)
{
_userMessage = new UserMessage();
_userMessage.SummaryMessage = summaryMessage;
_userMessage.ShowMessages = showIndividualMessages;
_userMessage.ShowAsError = showAsError;
}
public static string DisplayUserMessages()
{
if (_userMessage == null)
return string.Empty;
StringBuilder messageString = new StringBuilder();
messageString.AppendFormat("\n");
messageString.AppendLine(string.Format("<div class=\"messageSummary {0}\">", (_userMessage.ShowAsError) ? "invalid" : "valid"));
messageString.AppendLine(string.Format("<h3>{0}</h3>", _userMessage.SummaryMessage));
messageString.AppendLine("</div>");
return messageString.ToString();
}
The problem I have is that the _userMessage variable has to be a static variable, otherwise I get the error message "An object reference is required for the non-static field.......". The problem with the variable being static is that is stays in memory, so if the user receives an error message and then visits another page - the error message is still displayed!
I'm sure this is because I missed OOP 101, but how should I correct this?
Do not use static variable to keep messages per user! ASP.NET application is multi-threaded and using static variable is not thread safe. Store them in Session.
public static void LogSummary(string summaryMessage, ...)
{
HttpContext.Current.Session["userMessages"] = new UserMessage();
...
}
public static string DisplayUserMessages()
{
// get the value from session
var userMessage = (UserMessage)HttpContext.Current.Session["userMessages"];
// do the work
// do the clean up
HttpContext.Current.Session["userMessages"] = null;
// the messages will not be displayed on next request
}
Each request is handled by different thread, so the users will overwrite the _userMessage field and you cannot guarantee that messages for the current user will be displayed.
Pass the reference as an argument to the static member, or have it return a new instance like below:
public static UserMessage LogSummary(string summaryMessage, bool showIndividualMessages, bool showAsError)
{
var userMessage = new UserMessage();
userMessage.SummaryMessage = summaryMessage;
userMessage.ShowMessages = showIndividualMessages;
userMessage.ShowAsError = showAsError;
return userMessage;
}
In my opinion you try to face a problem with a wrong approach. Considering that you're developing service side component (ASP.NET) and you have to have perfect isolation between every user visits your site, I personally don't see any reason why do not use a backend database for error message holding where every record can be associated to a single user unique ID.
The simple ACID supported database (in practice almost any on the market) is a perfect fit in this case.
In this way you can pull from the database the message you need at the moment you need, and don't need more worry about any type of memory issue (at least from the perspective of this question)
Hope this helps.
Static variable will be shared within AppDomain - i.e. concurrent requests will share the same instance and hence your approach is problematic.
You should consider putting your user-message instance into the current HttpContext to get per request semantics as needed by your use case. For example,
public class UserMessage
{
public static UserMessage Current
{
get { return HttpContext.Current.Items["_User_Message"] as UserMessage; }
}
public static void LogSummary(string summaryMessage, bool showIndividualMessages, bool showAsError)
{
var userMessage = new UserMessage();
userMessage.SummaryMessage = summaryMessage;
...
HttpContext.Current.Items["_User_Message"] = userMessage;
}
public static string DisplayUserMessages()
{
var userMessage = UserMessage.Current;
if (userMessage == null ) return string.Empty;
...
}
// rest of the code
...
}
I would probably also make UserMessage constructor private.

Categories