Click here to Skip to main content
15,880,891 members
Articles / Programming Languages / C#

Monitoring Attribute Value Changes inside a Class

Rate me:
Please Sign up or sign in to vote.
4.31/5 (8 votes)
7 Jan 2012CPOL3 min read 24.7K   477   17   5
A class that allows you to monitor the actual change of a variable and notifies all interested objects with an event

Introduction

Consider the case when there's a need to monitor the change of a class attribute. Each time the change occurs, an event should be raised to notify all interested objects. For this, I have developed a simple class which I often use.

Here's an example of such a need: we have a class, working with a database, which often executes queries. And we need monitoring the database channel state - whether it's OK or not.

Background

To achieve this, each time we have a successful query, we see if the connection is OK, and when the query fails because of the database connection - the channel state becomes disconnected.

We then have something like this:

C#
public class DBGateway
{
    private bool connectionIsOk = false;

    public bool ConnectionIsOK 
    {
        get { return connectionIsOk; }
        private set 
        {
                        connectionIsOk = value;
            if (connectionIsOk == false && value == true)
                RaiseConnectionRestored();
            if (connectionIsOk == true && value == false)
                RaiseConnectionLost();
        }
    }

    private string connectionString;

    public void ExecuteQuery()
    {
        try
        {
            //...some useful staff: connection to database, and so on
            ConnectionIsOK  = true;  //because we are here, 
                                     //and no exception occured - then it's OK
        }
        catch(SqlException)
        {
            ConnectionIsOK = false;
            throw;
        }
    }

    private void RaiseConnectionRestored()
    {
        if (ConnectionRestored != null) ConnectionRestored(this, EventArgs.Empty);
    }    

    private void RaiseConnectionLost()
    {
        if (ConnectionLost!= null) ConnectionLost(this, EventArgs.Empty);
    }

    public event EventHandler ConnectionRestored;
    
    public event EventHandler ConnectionLost;
}

The wrong thing about this code is that the database gateway class has an additional responsibility. We've got two events, functions for raising these events, and the logic for checking whether the value really changed.

The ValueMonitor<T> Class

ValueMonitor is a simple class which encapsulates the logic of change checks. It has a ValueChanged event, a Value property, and a constructor which allows you to set the initial value of the monitored variable.

We need to pay special attention to value and reference types. The Equals function returns what is really expected for the value types.

However, the result of equality comparison for reference types is the result of "pointers" comparison. Not what we actually need. That's why for reference types IEqualityComparer is expected in the overloaded constructor version.

ValueMonitorDescription/ClassDiagram.png

Consider the value change check code:

C#
public class ValueMonitor<ValueType>:IValueMonitor<ValueType>
{
    private ValueType aValue = default(ValueType);
    private IEqualityComparer<ValueType> comparer = null;

    //all other members are ommited ...    

    public ValueType Value
    {
        get { return aValue; }
        set
        {
            bool areEqual = false;
            if (comparer == null)
                areEqual = (aValue.Equals(value));
            else areEqual = comparer.Equals(aValue, value);

            if (areEqual == true) return;
                ValueType oldValue = aValue; // remember previous for the event rising
            aValue = value;
            if (ValueChanged != null)
                ValueChanged(oldValue, aValue);
        }
    }
}

Using the Code

Now the code for our DBGateway class will look like this:

C#
public class DBGateway
{
    private ValueMonitor<bool> connectionIsOk = new ValueMonitor<bool>(false);

    public IValueMonitor<bool> ConnectionIsOK 
    {
        get { return connectionIsOk; }
    }

    private string connectionString;

    public void ExecuteQuery()
    {
        try
        {
            //...some useful staff: connection to database, and so on
            connectionIsOk.Value  = true; //because we a here, 
                                          //and no exception occured - then it's OK
        }
        catch(SqlException)
        {
            connectionIsOk.Value = false;
            throw;
        }
    }
}

As you see, we got rid of additional logic, and our class became lighter, and we now can concentrate on the DB code rather than the value change monitoring.

Example Application

Of course, in the example code, we don't monitor the database connection. To see the working of the class, the user sets values true and false to the status variable inside the Form class.

The form handles the ValueChanged event and shows the time of actual change of the variable.

ValueMonitorDescription/lastUpdated.gif

Clicking the same button several times gives no effect. Changing the button does.

Points of interest

Usage examples:

  • Monitoring state of any kind of channel like in the DBGateway example.
  • Monitoring the change of state of an object. Imagine we have an implementation of the State pattern and we want to be aware of the current state and its change. Then we have an enumeration like this:
    C#
    public enum ObjectState
    {
       Disconnected,
       LoggingIn,
       Normal
    }

    Then, to provide value change monitoring, we add something like:

    C#
    ValueMonitor<ObjectState> currentState = 
             new ValueMonitor<ObjectState>(ObjectState.Disconnected);
  • The case when you receive the traffic from another client application and you'd like to monitor the IP address of the currently connected one. The situation is not so rare: two hosts may use different channels, and when one fails, the other (backup host) connects and the system is still stable.

History

  • 7.01.2012 - First version
  • 8.01.2012 - After Ravi Bhavnani's remark, the first example of DBGateway was changed. The line:
    C#
    connectionIsOk = true;

    was added into the ConnectionIsOK property.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Crypton-M
Ukraine Ukraine
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 4 Pin
johannesnestler2-May-14 23:41
johannesnestler2-May-14 23:41 
GeneralMy vote of 4 Pin
SandroBoz9-Jan-12 21:41
SandroBoz9-Jan-12 21:41 
GeneralRe: My vote of 4 Pin
kosmoh10-Jan-12 0:29
kosmoh10-Jan-12 0:29 
Thanks. As for my first article - not so bad result. I expected worse Smile | :)
GeneralError in original DBGateway example? Pin
Ravi Bhavnani7-Jan-12 16:29
professionalRavi Bhavnani7-Jan-12 16:29 
GeneralRe: Error in original DBGateway example? Pin
kosmoh7-Jan-12 21:57
kosmoh7-Jan-12 21:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.