1. class NotifyPropertyChanged : INotifyPropertyChanged
  2. {
  3.     public event PropertyChangedEventHandler PropertyChanged;
  4.    
  5.     protected virtual void RaisePropertyChanged()
  6.     {
  7.         var frames = new StackTrace();
  8.         for (var i = 0; i < frames.FrameCount; i++)
  9.         {
  10.             var frame = frames.GetFrame(i).GetMethod() as MethodInfo;
  11.             if (frame != null)
  12.             {
  13.                 if (frame.IsSpecialName && frame.Name.StartsWith("set_"))
  14.                 {
  15.                     RaisePropertyChanged(frame.Name.Substring(4));
  16.                     return;
  17.                 }
  18.             }
  19.         }
  20.         throw new InvalidOperationException("NotifyPropertyChanged() can only by invoked within a property setter.");
  21.     }
  22.    
  23.     protected void RaisePropertyChanged(string propertyName)
  24.     {
  25.         PropertyChangedEventHandler handler = this.PropertyChanged;
  26.         if (handler != null)
  27.         {
  28.             handler(this, new PropertyChangedEventArgs(propertyName));
  29.         }
  30.     }
  31. }
  32.  
  33. class Notifier : NotifyPropertyChanged
  34. {
  35.     string _name1 = "";
  36.     public string Name1
  37.     {
  38.         get
  39.         {
  40.             return _name1;
  41.         }
  42.         [MethodImpl(MethodImplOptions.NoInlining)]
  43.         set
  44.         {
  45.             _name1 = value;
  46.             RaisePropertyChanged();
  47.         }
  48.     }
  49.    
  50.     string _name2 = "";
  51.     public string Name2
  52.     {
  53.         get
  54.         {
  55.             return _name2;
  56.         }
  57.         set
  58.         {
  59.             _name2 = value;
  60.             RaisePropertyChanged("Name2");
  61.         }
  62.     }
  63. }
  64.  
  65. public static void Main()
  66. {
  67.     const int N = 1000;
  68.    
  69.     var x = new Notifier();
  70.    
  71.     Console.WriteLine("Verifying that this will even work...");
  72.    
  73.     PropertyChangedEventHandler handler = (sender, e) => { Console.WriteLine(e.PropertyName); };
  74.     x.PropertyChanged += handler;
  75.    
  76.     x.Name1 = "Test Name1 value";
  77.     x.Name2 = "Test Name2 value";
  78.    
  79.     x.PropertyChanged -= handler;
  80.    
  81.     Console.WriteLine("Done. Press Enter to begin.");
  82.     Console.ReadLine();
  83.    
  84.     var sw = Stopwatch.StartNew();
  85.     for (int i = 0; i < N; ++i)
  86.     {
  87.         x.Name1 = "Whatever";
  88.     }
  89.     sw.Stop();
  90.    
  91.     TimeSpan elapsed1 = sw.Elapsed;
  92.    
  93.     Console.WriteLine("Raised event using reflection {0} times in {1} ms.", N, elapsed1.TotalMilliseconds);
  94.    
  95.     sw = Stopwatch.StartNew();
  96.     for (int i = 0; i < N; ++i)
  97.     {
  98.         x.Name2 = "Whatever";
  99.     }
  100.     sw.Stop();
  101.    
  102.     TimeSpan elapsed2 = sw.Elapsed;
  103.    
  104.     Console.WriteLine("Raised event WITHOUT reflection {0} times in {1} ms.", N, elapsed2.TotalMilliseconds);
  105. }