Observer mode-Event Implementation Scheme

Source: Internet
Author: User

The delegate is the type-safe callback mechanism provided by. Net Framework. The delegate is essentially a class. The class implements the constructor with method pointers, Invoke, BeginInvoke, and EndInvoke methods. Of course, these tasks are all done by CLR and compiler. The event is based on the delegate. CLR secretly helps us convert an event into a private field and two public methods. A private field is a private delegate field, and two public methods are secure calls to add and remove delegate fields. This article focuses not on delegation and event mechanisms, but on how to easily implement project requirements through events.

For convenience, I will describe the project requirements again.

There is a project with multiple types of sensors, including pressure sensors, displacement sensors, and vibration sensors. Each type has several sensors, specific operations on each sensor will lead to a variety of display functions such as historical graphs, real-time bar charts, real-time data tables, and status display.

In this way, we also implement the real-time data table function of the pressure sensor through specific operations in a test-driven way.

The test code segment is the same as the Observer PULL mode. For more information, see Code List 1. The function is implemented in code list 2, 3, and 4.

Code List 1 PressureSensorAndDataTableTest. cs

namespace RTChangeData{    [TestFixture]    class PressureSensorAndDataTableTest    {        [Test]        public void PressureSensorChanged()        {            PressureSensorSubject ps = new PressureSensorSubject(5);            DataTableObserver dt = new DataTableObserver(ps);                        ps.Channel1Data = 1;            ps.Channel2Data = 2;            Assert.AreEqual(ps.ID, dt.ID, "ID Not Equal.");            Assert.AreEqual(ps.Channel1Data, dt.Channel1Data, "Channel1 Data Not Equal.");            Assert.AreEqual(ps.Channel2Data, dt.Channel2Data, "Channel2 Data Not Equal.");        }    }}

Code List 2 Subject. cs

namespace RTChangeDataByEvent{    public interface Subject    {        event EventHandler
 
   Channel1DataChanged;        event EventHandler
  
    Channel2DataChanged;    }    public class PSEventArgs : EventArgs    {        public int NewValue { get; set; }        public int ID { get; set; }        public PSEventArgs(int id, int newValue)        {            ID = id;            NewValue = newValue;        }    }}
  
 

Code List 3 PressureSensorSubject. cs

Namespace RTChangeDataByEvent {public class PressureSensorSubject: Subject {private int m_id; private int m_channel1Data; private int m_channel2Data; public int Channel1Data {get {return m_channel1Data;} set {m_channel1Data = value; onChannel1DataChanged (new incluventargs (m_id, value) ;}public int Channel2Data {get {return m_channel2Data;} set {m_channel2Data = value; OnChannel2DataChanged (new incluventargs (m_id, value) ;}} public object ID {get; set;} public event EventHandler
 
  
Channel1DataChanged; public event EventHandler
  
   
Channel2DataChanged; public PressureSensorSubject (int id) {this. m_id = id;} protected virtual void OnChannel1DataChanged (venture ventargs e) {// call EventHandler in thread-Safe Mode
   
    
Tmp = Interlocked. CompareExchange
    
     
> (Ref Channel1DataChanged, null, null); if (tmp! = Null) {tmp. Invoke (this, e) ;}} protected virtual void OnChannel2DataChanged (venture ventargs e) {// call EventHandler in thread-Safe Mode
     
      
Tmp = Interlocked. CompareExchange
      
        > (Ref Channel2DataChanged, null, null); if (tmp! = Null) {tmp. Invoke (this, e );}}}}
      
     
    
   
  
 

Code list 4 DataTableObserver. cs

namespace RTChangeDataByEvent{    class DataTableObserver    {        public object ID { get; set; }        public object Channel1Data { get; set; }        public object Channel2Data { get; set; }        public DataTableObserver(Subject ps)        {            ps.Channel1DataChanged += new EventHandler
 
  ((sender, e) =>            {                this.ID = e.ID;                Channel1Data = e.NewValue;            });            ps.Channel2DataChanged += new EventHandler
  
   ((sender, e) =>            {                Channel2Data = e.NewValue;                PressureSensorSubject pss = sender as PressureSensorSubject;                if (pss != null)                {                    ID = pss.ID;                }            });        }                  }}
  
 

Is it found that the class structure is very different from that of the Observer? New technologies can often influence design methods. Next we will describe the class diagram and then introduce the features of event implementation.


Figure 1 event observer Mode

As shown in figure 1, the parameter class ventargs is added, the Observer class is removed, and the dependency between Observer and Subject is reversed. DataTableObserver also relies on interfaces to meet the DIP principle. Note that there should be two functions in DataTableObserver, which implement the operations that should be performed when the Subject event is triggered. The lambda expression used in code 4. It is elegant and intuitive to use lambda expressions when a function can be implemented in just two or three rows. If you need a long paragraph, we recommend that you use the new delegate object method passed in the constructor. It is also easy to implement the project requirements on the basis of figure 1. Different subject interface methods can be designed for different sensors to inherit and implement interfaces in the corresponding classes. Then, the Observer registers the corresponding event after observing the event.

Conclusion:

The design pattern is an ideological pattern, and its specific implementation will undergo subtle changes based on different languages .. The delegate and event in Net is the security encapsulation of callback, and is the implementation scheme of the default observer push mode. Because the. Net event mode mostly occurs on the interface, when accessing a single thread, you can directly determine whether the event is empty and then call the event without using the Interlocked. CompareExchange method.

The similarities and differences between events and delegation involve many details of CLR. The combination of delegation and reflection can also surprise us a lot. We will discuss it later.


Reprinted, please indicate the source. The Code download page of this article: Observer mode event implementation solution

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.