Hiểu các sự kiện và xử lý sự kiện trong C #


329

Tôi hiểu mục đích của các sự kiện, đặc biệt là trong bối cảnh tạo giao diện người dùng. Tôi nghĩ rằng đây là nguyên mẫu để tạo ra một sự kiện:

public void EventName(object sender, EventArgs e);

Những người xử lý sự kiện làm gì, tại sao họ cần và làm cách nào để tạo một cái?


9
Theo ghi nhận của @Andy, đoạn mã ở đây mô tả phương thức đã đăng ký cho sự kiện, chứ không phải chính sự kiện.
dthrasher


Câu trả lời:


659

Để hiểu các trình xử lý sự kiện, bạn cần hiểu các đại biểu . Trong C # , bạn có thể nghĩ về một đại biểu như một con trỏ (hoặc một tham chiếu) cho một phương thức. Điều này rất hữu ích vì con trỏ có thể được truyền xung quanh dưới dạng giá trị.

Khái niệm trung tâm của một đại biểu là chữ ký hoặc hình dạng của nó. Đó là (1) kiểu trả về và (2) các đối số đầu vào. Ví dụ: nếu chúng ta tạo một đại biểu void MyDelegate(object sender, EventArgs e), nó chỉ có thể trỏ đến các phương thức trả về voidvà lấy objectEventArgs . Kiểu như một cái lỗ vuông và một cái chốt vuông. Vì vậy, chúng tôi nói các phương thức này có cùng chữ ký, hoặc hình dạng, như đại biểu.

Vì vậy, biết cách tạo tham chiếu đến một phương thức, hãy nghĩ về mục đích của các sự kiện: chúng tôi muốn khiến một số mã được thực thi khi có điều gì đó xảy ra ở nơi khác trong hệ thống - hoặc "xử lý sự kiện". Để làm điều này, chúng tôi tạo các phương thức cụ thể cho mã mà chúng tôi muốn được thực thi. Chất keo giữa sự kiện và các phương thức được thực hiện là các đại biểu. Sự kiện phải lưu trữ bên trong một "danh sách" các con trỏ tới các phương thức để gọi khi sự kiện được nêu ra. * Tất nhiên, để có thể gọi một phương thức, chúng ta cần biết các đối số nào để truyền cho nó! Chúng tôi sử dụng đại biểu làm "hợp đồng" giữa sự kiện và tất cả các phương thức cụ thể sẽ được gọi.

Vì vậy, mặc định EventHandler(và nhiều cái giống như vậy) đại diện cho một hình dạng cụ thể của phương thức (một lần nữa, void / object-EventArss). Khi bạn khai báo một sự kiện, bạn đang nói hình dạng của phương thức (EventHandler) mà sự kiện đó sẽ gọi, bằng cách chỉ định một đại biểu:

//This delegate can be used to point to methods
//which return void and take a string.
public delegate void MyEventHandler(string foo);

//This event can cause any method which conforms
//to MyEventHandler to be called.
public event MyEventHandler SomethingHappened;

//Here is some code I want to be executed
//when SomethingHappened fires.
void HandleSomethingHappened(string foo)
{
    //Do some stuff
}

//I am creating a delegate (pointer) to HandleSomethingHappened
//and adding it to SomethingHappened's list of "Event Handlers".
myObj.SomethingHappened += new MyEventHandler(HandleSomethingHappened);

//To raise the event within a method.
SomethingHappened("bar");

(* Đây là chìa khóa cho các sự kiện trong .NET và loại bỏ "ma thuật" - một sự kiện thực sự, dưới vỏ bọc, chỉ là một danh sách các phương thức có cùng "hình dạng". Danh sách được lưu trữ tại nơi sự kiện tồn tại. sự kiện được "nêu ra", thực sự chỉ là "đi qua danh sách các phương thức này và gọi từng phương thức, sử dụng các giá trị này làm tham số". Chỉ định một trình xử lý sự kiện chỉ là cách dễ dàng hơn để thêm phương thức của bạn vào danh sách phương thức này được gọi là).


24
Và bây giờ có ai có thể giải thích tại sao sự kiện này được gọi là EventHandler không ?? Trong tất cả các quy ước đặt tên khó hiểu, đây là điều tồi tệ nhất ...
Joel ở Gô

37
@Joel in Go sự kiện không được gọi là EventHandler - EventHandler là hợp đồng mà sự kiện phải có với bất kỳ ai giao tiếp với nó. Nó giống như "chuỗi MyString" - chuỗi đang khai báo kiểu. sự kiện MyEventHandler TheEvent đang tuyên bố rằng bất kỳ ai tương tác với sự kiện này đều phải tuân thủ hợp đồng MyEventHandler. Công ước Handler là vì hợp đồng chủ yếu mô tả cách xử lý sự kiện.
Rex M

18
Sự kiện bị sa thải như thế nào?
thuật giả kim

17
@Rex M: cảm ơn bạn vì lời giải thích mạch lạc đầu tiên cho "MyEventHandler" mà tôi từng thấy :)
Joel trong Gô

10
Cảm ơn bạn về giai đoạn: "Chất keo giữa sự kiện và phương thức được thực hiện là các đại biểu.", Điều này thực sự tuyệt vời.
zionpi

103

C # biết hai thuật ngữ, delegateevent. Hãy bắt đầu với cái đầu tiên.

Đại biểu

A delegatelà một tham chiếu đến một phương thức. Giống như bạn có thể tạo một tham chiếu đến một thể hiện:

MyClass instance = myFactory.GetInstance();

Bạn có thể sử dụng một đại biểu để tạo một tham chiếu đến một phương thức:

Action myMethod = myFactory.GetInstance;

Bây giờ bạn có tham chiếu này đến một phương thức, bạn có thể gọi phương thức đó qua tham chiếu:

MyClass instance = myMethod();

Nhưng tại sao bạn? Bạn cũng có thể chỉ cần gọimyFactory.GetInstance() trực tiếp. Trong trường hợp này bạn có thể. Tuy nhiên, có nhiều trường hợp để suy nghĩ về nơi bạn không muốn phần còn lại của ứng dụng có kiến ​​thức về myFactoryhoặc gọimyFactory.GetInstance() trực tiếp.

Một điều hiển nhiên là nếu bạn muốn có thể thay thế myFactory.GetInstance()vàomyOfflineFakeFactory.GetInstance() từ một vị trí trung tâm (hay còn gọi là factory method ).

Mô hình phương pháp nhà máy

Vì vậy, nếu bạn có một TheOtherClasslớp và nó cần sử dụng myFactory.GetInstance(), đây là cách mã sẽ trông như thế nào khi không có đại biểu (bạn sẽ cần phải TheOtherClassbiết về loại của bạn myFactory):

TheOtherClass toc;
//...
toc.SetFactory(myFactory);


class TheOtherClass
{
   public void SetFactory(MyFactory factory)
   {
      // set here
   }

}

Nếu bạn sử dụng đại biểu, bạn không phải để lộ loại nhà máy của tôi:

TheOtherClass toc;
//...
Action factoryMethod = myFactory.GetInstance;
toc.SetFactoryMethod(factoryMethod);


class TheOtherClass
{
   public void SetFactoryMethod(Action factoryMethod)
   {
      // set here
   }

}

Vì vậy, bạn có thể cho một đại biểu cho một số lớp khác để sử dụng, mà không để lộ loại của bạn cho họ. Điều duy nhất bạn phơi bày là chữ ký của phương thức của bạn (bạn có bao nhiêu tham số và như vậy).

"Chữ ký của phương pháp của tôi", trước đây tôi đã nghe điều đó ở đâu? Ồ vâng, giao diện !!! giao diện mô tả chữ ký của cả một lớp. Hãy nghĩ về các đại biểu như mô tả chữ ký của chỉ một phương pháp!

Một điểm khác biệt lớn giữa giao diện và đại biểu là khi bạn viết lớp, bạn không cần phải nói với C # "phương thức này thực hiện kiểu đại biểu đó". Với các giao diện, bạn cần phải nói "lớp này thực hiện kiểu giao diện đó".

Hơn nữa, một tham chiếu đại biểu có thể (với một số hạn chế, xem bên dưới) tham chiếu nhiều phương thức (được gọi là MulticastDelegate ). Điều này có nghĩa là khi bạn gọi đại biểu, nhiều phương thức được đính kèm rõ ràng sẽ được thực thi. Một tham chiếu đối tượng luôn có thể chỉ tham chiếu đến một đối tượng.

Các hạn chế đối với a MulticastDelegatelà chữ ký (phương thức / ủy nhiệm) không được có bất kỳ giá trị trả về ( void) nào và các từ khóa outrefkhông được sử dụng trong chữ ký. Rõ ràng, bạn không thể gọi hai phương thức trả về một số và mong đợi chúng trả về cùng một số. Khi chữ ký tuân thủ, đại biểu sẽ tự động a MulticastDelegate.

Biến cố

Các sự kiện chỉ là các thuộc tính (như get; set; thuộc tính cho các trường đối tượng) hiển thị đăng ký cho đại biểu từ các đối tượng khác. Tuy nhiên, các thuộc tính này không hỗ trợ get; set;. Thay vào đó, họ hỗ trợ thêm; tẩy;

Vì vậy, bạn có thể có:

    Action myField;

    public event Action MyProperty
    {
        add { myField += value; }
        remove { myField -= value; }
    }

Sử dụng trong UI (WinForms, WPF, UWP, v.v.)

Vì vậy, bây giờ chúng ta biết rằng một đại biểu là một tham chiếu đến một phương thức và chúng ta có thể có một sự kiện để cho thế giới biết rằng họ có thể cung cấp cho chúng ta các phương thức của họ để được tham chiếu từ đại biểu của chúng ta và sau đó chúng ta là một nút UI có thể hỏi bất cứ ai quan tâm đến việc tôi đã được nhấp hay không, để đăng ký phương thức của họ với chúng tôi (thông qua sự kiện chúng tôi tiếp xúc). Chúng tôi có thể sử dụng tất cả các phương pháp đã được trao cho chúng tôi và tham chiếu chúng bởi đại biểu của chúng tôi. Và sau đó, chúng tôi sẽ chờ và đợi .... cho đến khi một người dùng đến và nhấp vào nút đó, thì chúng tôi sẽ có đủ lý do để triệu tập đại biểu. Và bởi vì đại biểu tham chiếu tất cả các phương thức được cung cấp cho chúng tôi, tất cả các phương thức đó sẽ được gọi. Chúng ta không biết những phương thức đó làm gì, chúng ta cũng không biết lớp nào thực hiện các phương thức đó. Tất cả những gì chúng tôi quan tâm là ai đó quan tâm đến việc chúng tôi được nhấp vào,

Java

Các ngôn ngữ như Java không có đại biểu. Họ sử dụng giao diện thay thế. Cách họ làm là yêu cầu bất kỳ ai quan tâm đến 'chúng tôi được nhấp', để thực hiện một giao diện nhất định (với một phương thức nhất định mà chúng tôi có thể gọi), sau đó cung cấp cho chúng tôi toàn bộ ví dụ thực hiện giao diện. Chúng tôi giữ một danh sách tất cả các đối tượng thực hiện giao diện này và có thể gọi 'phương thức nhất định mà chúng tôi có thể gọi' bất cứ khi nào chúng tôi được nhấp.


cổ vũ cho lời giải thích nhưng làm thế nào một sự kiện khác với một trường hợp của một đại biểu đảm nhận người đăng ký? cả hai trông giống hệt nhau?
BKSpurgeon

@BKSpurgeon đó là vì họ "đại biểu nhận người đăng ký" - eventchỉ là cú pháp đường, không có gì hơn.
Mathieu Guindon

"Các hạn chế đối với MulticastDelegate là chữ ký (phương thức / ủy nhiệm) không được có bất kỳ giá trị trả về (void) nào", tôi không nghĩ rằng điều này là chính xác. Nếu họ có giá trị trả về, nó sẽ trả về giá trị cuối cùng.
Hozikimaru

"Do đó, bạn có thể cho một đại biểu cho một số lớp khác sử dụng, mà không để lộ loại của bạn cho họ. Điều duy nhất bạn phơi bày là chữ ký của phương thức của bạn ..." - với tôi đó là điểm quan trọng. Cảm ơn bạn!
Ryan

40

Đó thực sự là tuyên bố cho một trình xử lý sự kiện - một phương thức sẽ được gọi khi một sự kiện được kích hoạt. Để tạo sự kiện, bạn sẽ viết một cái gì đó như thế này:

public class Foo
{
    public event EventHandler MyEvent;
}

Và sau đó bạn có thể đăng ký vào sự kiện như thế này:

Foo foo = new Foo();
foo.MyEvent += new EventHandler(this.OnMyEvent);

Với OnMyEvent () được định nghĩa như thế này:

private void OnMyEvent(object sender, EventArgs e)
{
    MessageBox.Show("MyEvent fired!");
}

Bất cứ khi nào Footắt MyEvent, sau đó OnMyEventxử lý của bạn sẽ được gọi.

Bạn không phải luôn luôn sử dụng một thể hiện EventArgsnhư là tham số thứ hai. Nếu bạn muốn bao gồm thông tin bổ sung, bạn có thể sử dụng một lớp có nguồn gốc từ EventArgs( EventArgslà cơ sở theo quy ước). Ví dụ: nếu bạn xem một số sự kiện được xác định Controltrong WinForms hoặc FrameworkElementtrong WPF, bạn có thể thấy các ví dụ về các sự kiện truyền thông tin bổ sung cho trình xử lý sự kiện.


14
Cảm ơn bạn đã trả lời câu hỏi và không đi vào Đại biểu và Sự kiện.
split_byzero

3
Tôi khuyên bạn không nên sử dụng OnXXXmẫu đặt tên cho trình xử lý sự kiện của bạn. (Thật ngu ngốc, OnXXX được hiểu là 'xử lý XXX' trong MFC và 'nâng cao XXX' trong .net, và vì vậy bây giờ ý nghĩa của nó không rõ ràng và khó hiểu - xem bài đăng này để biết chi tiết ). Tên ưa thích sẽ là RaiseXXXđể nâng cao sự kiện và HandleXXXhoặc Sender_XXXcho người xử lý sự kiện.
Jason Williams

1
Bạn có thể hiển thị một ví dụ hoạt động với một ứng dụng WinForms đơn giản không?
MC9000

40

Đây là một ví dụ mã có thể giúp:

using System;
using System.Collections.Generic;
using System.Text;

namespace Event_Example
{
  // First we have to define a delegate that acts as a signature for the
  // function that is ultimately called when the event is triggered.
  // You will notice that the second parameter is of MyEventArgs type.
  // This object will contain information about the triggered event.

  public delegate void MyEventHandler(object source, MyEventArgs e);

  // This is a class which describes the event to the class that receives it.
  // An EventArgs class must always derive from System.EventArgs.

  public class MyEventArgs : EventArgs
  {
    private string EventInfo;

    public MyEventArgs(string Text) {
      EventInfo = Text;
    }

    public string GetInfo() {
      return EventInfo;
    }
  }

  // This next class is the one which contains an event and triggers it
  // once an action is performed. For example, lets trigger this event
  // once a variable is incremented over a particular value. Notice the
  // event uses the MyEventHandler delegate to create a signature
  // for the called function.

  public class MyClass
  {
    public event MyEventHandler OnMaximum;

    private int i;
    private int Maximum = 10;

    public int MyValue
    {
      get { return i; }
      set
      {
        if(value <= Maximum) {
          i = value;
        }
        else 
        {
          // To make sure we only trigger the event if a handler is present
          // we check the event to make sure it's not null.
          if(OnMaximum != null) {
            OnMaximum(this, new MyEventArgs("You've entered " +
              value.ToString() +
              ", but the maximum is " +
              Maximum.ToString()));
          }
        }
      }
    }
  }

  class Program
  {
    // This is the actual method that will be assigned to the event handler
    // within the above class. This is where we perform an action once the
    // event has been triggered.

    static void MaximumReached(object source, MyEventArgs e) {
      Console.WriteLine(e.GetInfo());
    }

    static void Main(string[] args) {
      // Now lets test the event contained in the above class.
      MyClass MyObject = new MyClass();
      MyObject.OnMaximum += new MyEventHandler(MaximumReached);
      for(int x = 0; x <= 15; x++) {
        MyObject.MyValue = x;
      }
      Console.ReadLine();
    }
  }
}

4
Yêu cầu đại biểu trong C # 6 có thể được đơn giản hóa thành:OnMaximum?.Invoke(this,new MyEventArgs("you've entered..."));
Tim Schmelter

23

Chỉ cần thêm vào các câu trả lời tuyệt vời hiện có ở đây - dựa trên mã trong câu được chấp nhận, sử dụng delegate void MyEventHandler(string foo)...

Bởi vì trình biên dịch biết loại đại biểu của sự kiện SomethingHappened , nên:

myObj.SomethingHappened += HandleSomethingHappened;

Hoàn toàn tương đương với:

myObj.SomethingHappened += new MyEventHandler(HandleSomethingHappened);

Và xử lý cũng có thể đăng ký với -=như thế này:

// -= removes the handler from the event's list of "listeners":
myObj.SomethingHappened -= HandleSomethingHappened;

Để hoàn thiện, việc nâng cao sự kiện có thể được thực hiện như thế này, chỉ trong lớp sở hữu sự kiện:

//Firing the event is done by simply providing the arguments to the event:
var handler = SomethingHappened; // thread-local copy of the event
if (handler != null) // the event is null if there are no listeners!
{
    handler("Hi there!");
}

Cần có bản sao xử lý cục bộ của trình xử lý để đảm bảo lệnh được an toàn cho luồng - nếu không thì một luồng có thể đi và hủy đăng ký trình xử lý cuối cùng cho sự kiện ngay sau khi chúng tôi kiểm tra xem có phải không nullvà chúng tôi sẽ có một "trò vui" NullReferenceExceptionở đó .


C # 6 đã giới thiệu một bàn tay ngắn đẹp cho mẫu này. Nó sử dụng toán tử lan truyền null.

SomethingHappened?.Invoke("Hi there!");

13

Sự hiểu biết của tôi về các sự kiện là;

Đại biểu:

Một biến để giữ tham chiếu đến phương thức / phương thức được thực thi. Điều này làm cho nó có thể vượt qua các phương thức như một biến.

Các bước để tạo và gọi sự kiện:

  1. Sự kiện này là một ví dụ của một đại biểu

  2. Vì một sự kiện là một thể hiện của một đại biểu, nên trước tiên chúng ta phải xác định đại biểu.

  3. Chỉ định phương thức / phương thức sẽ được thực thi khi sự kiện được kích hoạt ( Gọi cho đại biểu )

  4. Cháy sự kiện ( Gọi cho đại biểu )

Thí dụ:

using System;

namespace test{
    class MyTestApp{
        //The Event Handler declaration
        public delegate void EventHandler();

        //The Event declaration
        public event EventHandler MyHandler;

        //The method to call
        public void Hello(){
            Console.WriteLine("Hello World of events!");
        }

        public static void Main(){
            MyTestApp TestApp = new MyTestApp();

            //Assign the method to be called when the event is fired
            TestApp.MyHandler = new EventHandler(TestApp.Hello);

            //Firing the event
            if (TestApp.MyHandler != null){
                TestApp.MyHandler();
            }
        }

    }   

}

3

nhà xuất bản: nơi các sự kiện xảy ra. Nhà xuất bản nên chỉ định lớp ủy nhiệm nào đang sử dụng và tạo các đối số cần thiết, truyền các đối số đó và chính nó cho đại biểu.

thuê bao: nơi phản ứng xảy ra. Thuê bao nên chỉ định phương pháp để đáp ứng với các sự kiện. Các phương thức này sẽ có cùng loại đối số như đại biểu. Thuê bao sau đó thêm phương thức này vào đại biểu của nhà xuất bản.

Do đó, khi sự kiện xảy ra trong nhà xuất bản, đại biểu sẽ nhận được một số đối số sự kiện (dữ liệu, v.v.), nhưng nhà xuất bản không biết điều gì sẽ xảy ra với tất cả các dữ liệu này. Người đăng ký có thể tạo các phương thức trong lớp của riêng họ để phản hồi các sự kiện trong lớp của nhà xuất bản, để người đăng ký có thể trả lời các sự kiện của nhà xuất bản.


2
//This delegate can be used to point to methods
//which return void and take a string.
public delegate void MyDelegate(string foo);

//This event can cause any method which conforms
//to MyEventHandler to be called.
public event MyDelegate MyEvent;

//Here is some code I want to be executed
//when SomethingHappened fires.
void MyEventHandler(string foo)
{
    //Do some stuff
}

//I am creating a delegate (pointer) to HandleSomethingHappened
//and adding it to SomethingHappened's list of "Event Handlers".
myObj.MyEvent += new MyDelegate (MyEventHandler);

0

Tôi đồng ý với KE50 ngoại trừ việc tôi xem từ khóa 'sự kiện' là bí danh cho 'ActionCollection' vì sự kiện này chứa một tập hợp các hành động sẽ được thực hiện (ví dụ: đại biểu).

using System;

namespace test{

class MyTestApp{
    //The Event Handler declaration
    public delegate void EventAction();

    //The Event Action Collection 
    //Equivalent to 
    //  public List<EventAction> EventActions=new List<EventAction>();
    //        
    public event EventAction EventActions;

    //An Action
    public void Hello(){
        Console.WriteLine("Hello World of events!");
    }
    //Another Action
    public void Goodbye(){
        Console.WriteLine("Goodbye Cruel World of events!");
    }

    public static void Main(){
        MyTestApp TestApp = new MyTestApp();

        //Add actions to the collection
        TestApp.EventActions += TestApp.Hello;
        TestApp.EventActions += TestApp.Goodbye;

        //Invoke all event actions
        if (TestApp.EventActions!= null){
            //this peculiar syntax hides the invoke 
            TestApp.EventActions();
            //using the 'ActionCollection' idea:
            // foreach(EventAction action in TestApp.EventActions)
            //     action.Invoke();
        }
    }

}   

}

0

Câu trả lời kỹ thuật tuyệt vời trong bài! Tôi không có gì về mặt kỹ thuật để thêm vào đó.

Một trong những lý do chính tại sao các tính năng mới xuất hiện trong ngôn ngữ và phần mềm nói chung là tiếp thị hoặc chính trị công ty! :-) Điều này không được ước tính!

Tôi nghĩ rằng điều này áp dụng cho một số mở rộng nhất định cho các đại biểu và các sự kiện quá! tôi thấy chúng hữu ích và thêm giá trị cho ngôn ngữ C #, nhưng mặt khác, ngôn ngữ Java đã quyết định không sử dụng chúng! họ quyết định rằng bất cứ điều gì bạn đang giải quyết với các đại biểu bạn đã có thể giải quyết bằng các tính năng hiện có của ngôn ngữ, ví dụ:

Bây giờ, khoảng năm 2001, Microsoft đã phát hành .NET framework và ngôn ngữ C # như một giải pháp cạnh tranh với Java, vì vậy thật tốt khi có những TÍNH NĂNG MỚI mà Java không có.


0

Gần đây tôi đã làm một ví dụ về cách sử dụng các sự kiện trong c # và đăng nó lên blog của mình. Tôi đã cố gắng làm cho nó rõ ràng nhất có thể, với một ví dụ rất đơn giản. Trong trường hợp nó có thể giúp bất cứ ai, đây là: http://www.konsfik.com/USE-events-in-csharp/

Nó bao gồm mô tả và mã nguồn (có nhiều bình luận), và nó chủ yếu tập trung vào việc sử dụng các sự kiện và xử lý sự kiện thích hợp (giống như mẫu).

Một số điểm chính là:

  • Các sự kiện giống như "các loại đại biểu phụ", chỉ bị ràng buộc nhiều hơn (theo cách tốt). Trong thực tế, một tuyên bố của một sự kiện luôn bao gồm một đại biểu (EventHandlers là một loại đại biểu).

  • Trình xử lý sự kiện là các loại đại biểu cụ thể (bạn có thể nghĩ chúng là một mẫu), điều này buộc người dùng phải tạo các sự kiện có "chữ ký" cụ thể. Chữ ký có định dạng: (người gửi đối tượng, sự kiện EventArss).

  • Bạn có thể tạo lớp con EventArss của riêng mình, để bao gồm bất kỳ loại thông tin nào mà sự kiện cần truyền tải. Không cần thiết phải sử dụng EventHandlers khi sử dụng các sự kiện. Bạn hoàn toàn có thể bỏ qua họ và sử dụng loại đại biểu của riêng bạn ở vị trí của họ.

  • Một điểm khác biệt chính giữa việc sử dụng các sự kiện và đại biểu, là các sự kiện chỉ có thể được gọi từ bên trong lớp mà chúng được khai báo, mặc dù chúng có thể được khai báo là công khai. Đây là một điểm khác biệt rất quan trọng, vì nó cho phép các sự kiện của bạn được phơi bày để chúng được "kết nối" với các phương thức bên ngoài, đồng thời chúng được bảo vệ khỏi "lạm dụng bên ngoài".


0

Một điều khác cần biết , trong một số trường hợp, bạn phải sử dụng Đại biểu / Sự kiện khi bạn cần mức độ ghép thấp !

Nếu bạn muốn sử dụng một thành phần ở một vài nơi trong ứng dụng , bạn cần tạo một thành phần có mức độ khớp nối thấp và LOGIC không quan tâm cụ thể phải được ủy quyền NGOÀI TRỜI thành phần của bạn! Điều này đảm bảo rằng bạn có một hệ thống tách rời và mã sạch hơn.

Trong nguyên tắc RẮN, đây là " D ", ( D nguyên tắc đảo ngược ).

Còn được gọi là " IoC ", Đảo ngược điều khiển .

Bạn có thể tạo " IoC " với Sự kiện, Đại biểu và DI (Dependency Injection).

Thật dễ dàng để truy cập một phương thức trong một lớp con. Nhưng khó khăn hơn để truy cập một phương thức trong lớp cha mẹ từ con. Bạn phải truyền tài liệu tham khảo cho phụ huynh! (hoặc sử dụng DI với Giao diện)

Đại biểu / Sự kiện cho phép chúng tôi giao tiếp từ trẻ đến cha mẹ mà không cần tham khảo!

nhập mô tả hình ảnh ở đây

Trong sơ đồ này ở trên, tôi không sử dụng Delegate / Event và thành phần cha B phải có tham chiếu của thành phần cha mẹ A để thực hiện logic nghiệp vụ không quan tâm trong phương thức A. (mức độ khớp nối cao)

Với phương pháp này, tôi sẽ phải đặt tất cả các tham chiếu của tất cả các thành phần sử dụng thành phần B! :

nhập mô tả hình ảnh ở đây

Trong sơ đồ này ở trên, tôi sử dụng Delegate / Event và thành phần B không phải biết A. (mức độ ghép thấp)

Và bạn có thể sử dụng thành phần B của bạn ở bất cứ đâu trong ứng dụng của bạn !

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.