using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Chp04_events {
internal delegate void PriceChangedHandler( decimal oldPrice, decimal newPrice );
/// <summary>
/// "Broadcaster" class
/// </summary>
internal class Stock { string _symbol;
decimal _price;
public Stock( string symbol ) { this._symbol = symbol; }
// If you comment out this line and uncomment next line, "myStock.PriceChanged = ..." and "Delegate[] chain = " statements
// below in public void SetStockToWatch( Stock myStock ) methods would become legal, compromising an independence of event subscribers.
// That's why we use an `event` keyword, rather than simpli a delegate.
public event PriceChangedHandler PriceChanged;
//public PriceChangedHandler PriceChanged;
public decimal Price { get { return _price; } set { if (_price == value) return;
if (PriceChanged != null) { // Code within the Broadcaster type has full access to event and can treat it as delegate:
Delegate[] chain = PriceChanged.GetInvocationList();
Console.WriteLine( "There is/are {0} subscribers watching for event I'm broadcsting", chain.Length ); Console.WriteLine( "The first subscriber has a type of {0}", chain[0].Target.GetType() ); if (chain.Length > 1) { Console.WriteLine( "The second subscriber has a type of {0}", chain[1].Target.GetType() ); }
PriceChanged( _price, value );
}
_price = value;
}
}
}
/// <summary>
/// "Subscriber" class
/// </summary>
internal class StockWatcher { protected string _watcherName = String.Empty;
public StockWatcher( string watcherName ) { this._watcherName = watcherName;
}
public string WatcherName { get { return _watcherName; } }
public void SetStockToWatch( Stock myStock ) { myStock.PriceChanged += new PriceChangedHandler( myStock_PriceChanged );
// Code outside the Broadcaster type can only perform += an -=. "Subscriber" does not know about other "subscribers".
// The following line of code won't compile:
// Error: The event 'Chp04_events.Stock.PriceChanged' can only appear on the left hand side of += or -=
// (except when used from within the type 'Chp04_events.Stock')
myStock.PriceChanged = new PriceChangedHandler( myStock_PriceChanged );
// The same error:
Delegate[] chain = myStock.PriceChanged.GetInvocationList();
}
public void myStock_PriceChanged( decimal oldPrice, decimal newPrice ) { Console.WriteLine( "{0}: Stock price was changed from {1} to {2}", WatcherName, oldPrice, newPrice ); }
}
internal class NewStockWatcher : StockWatcher { public NewStockWatcher( string watcherName ) : base( watcherName ) { } }
class Program { static void Main( string[] args ) { decimal myDecPrice;
var myStock = new Stock( "Napster" );
var myStockWatcher1 = new StockWatcher( "First Watcher" );
var myStockWatcher2 = new NewStockWatcher( "Second Watcher" );
myStockWatcher1.SetStockToWatch( myStock );
myStockWatcher2.SetStockToWatch( myStock );
while (1 == 1) { Console.WriteLine( "Please enter new stock price:" );
string newStockPrice = Console.ReadLine();
if (newStockPrice == String.Empty) break;
if (Decimal.TryParse( newStockPrice, out myDecPrice ))
myStock.Price = myDecPrice;
}
}
}
}