.NET có tích hợp sẵn EventArgs <T> không?


84

Tôi đã sẵn sàng để tạo một lớp EventArgs chung cho các chuỗi sự kiện mang một đối số:

public class EventArg<T> : EventArgs
{
    // Property variable
    private readonly T p_EventData;

    // Constructor
    public EventArg(T data)
    {
        p_EventData = data;
    }

    // Property for EventArgs argument
    public T Data
    {
        get { return p_EventData; }
    }
}

Trước khi tôi làm điều đó, C # có tính năng tương tự được tích hợp sẵn cho ngôn ngữ không? Tôi dường như nhớ lại đã gặp một cái gì đó như vậy khi C # 2.0 ra mắt, nhưng bây giờ tôi không thể tìm thấy nó.

Hay nói cách khác, tôi phải tạo lớp EventArgs chung của riêng mình hay C # cung cấp một lớp? Cảm ơn bạn đã giúp đỡ.


9
Bạn có thể đã thấyEventhandler<T>
Henk Holterman

1
Bạn có thể đã thấy EventArgs<T>trong mã dựa trên CAB / SCSF. Nó khá phổ biến trong các ứng dụng CAB / SCSF. Trong khi nó không phải là một phần của khuôn khổ này, có một EventArgs <T> thực hiện.
Shaun Wilson

Câu trả lời:


66

Không. Có thể bạn đang nghĩ đến EventHandler<T>, điều này cho phép bạn xác định đại diện cho bất kỳ loại EventArgs cụ thể nào.

Tuy nhiên, cá nhân tôi không cảm thấy điều đó EventArgs<T>khá phù hợp. Theo tôi, thông tin được sử dụng làm "trọng tải" trong các args sự kiện phải là một lớp tùy chỉnh để làm cho việc sử dụng và các thuộc tính mong đợi của nó rất rõ ràng. Sử dụng một lớp chung chung sẽ khiến bạn không thể đặt những cái tên có ý nghĩa vào đúng vị trí. ("Dữ liệu" đại diện cho điều gì?)


50
Trong các ứng dụng giống như MPI, tập trung vào dữ liệu, khá phổ biến khi thấy EventArgs <T> dùng để xử lý dữ liệu để các nhà phát triển có thể tận dụng hệ thống đăng ký / đăng ký loại an toàn, được tích hợp sẵn (Sự kiện .NET và Đại biểu), vì nó hoàn toàn không có ý nghĩa gì khi tạo các lớp con EventArgs chỉ để vận chuyển dữ liệu. Nếu mục đích của bạn là vận chuyển dữ liệu, có thể nói rằng sẽ hợp lý hơn khi xác định EventArgs <T>, bạn có thể phân lớp cho các mục đích sử dụng riêng biệt mà KHÔNG liên quan đến dữ liệu đang được vận chuyển. TL: DR Phần đầu tiên của câu trả lời này là thực tế và chính xác, phần thứ hai là chủ quan / ý kiến.
Shaun Wilson

1
Tôi cho rằng bạn đúng ... chống lại sự lười biếng đã đưa tôi đến đây. Nó giống như khi các nhà phát triển lười biếng sử dụng Tuple <,>. Đồ khủng khiếp.
CRice

Một điểm tốt, nhưng điều này về cơ bản sẽ hoạt động giống như Microsoft đã làm khi họ thêm thuộc tính Thẻ vào các lớp Điều khiển. Tất nhiên, chỉ coz 'MS đã làm nó, không làm cho nó đúng.
Ken Richards

1
Tôi đồng ý với người bình luận đầu tiên, toàn bộ nửa sau của câu trả lời này là một ý kiến ​​chủ quan / tôn giáo không mang tính xây dựng. :(
BrainSlugs83

5
Làm thế nào để EventHandler <Customer> hoặc EventHandler <Order> truyền tải bất kỳ thông tin ít hơn CustomerEventHandler hoặc OrderEventHandler ?
Hoàn toàn

33

Tôi phải nói rằng tôi không hiểu tất cả 'những người theo chủ nghĩa thuần túy' ở đây. tức là nếu bạn đã có một lớp túi được xác định - có tất cả các chi tiết cụ thể, thuộc tính, v.v. - tại sao hack lại tạo thêm một lớp không cần thiết chỉ để có thể tuân theo cơ chế sự kiện / args, kiểu chữ ký? điều là - không phải tất cả mọi thứ có trong .NET - hoặc 'bị thiếu' vì vấn đề đó - là 'tốt' - MS đã tự 'sửa chữa' trong nhiều năm ... Tôi muốn nói chỉ cần đi và tạo một cái - như tôi đã làm - vì tôi chỉ cần nó như vậy - và tiết kiệm cho tôi rất nhiều thời gian,


3
Trong trường hợp này, quan điểm của những người theo chủ nghĩa 'thuần túy' là làm cho ý định rõ ràng nhất có thể. Trong một ứng dụng sản xuất, tôi có hàng chục lớp EventArgs này. Một năm kể từ bây giờ, sẽ dễ hiểu hơn những gì tôi đã làm nếu tôi làm theo lời khuyên của Reed và tạo một lớp EventArgs tùy chỉnh.
David Veeneman

9
không có nghĩa là gắn nhãn cho bất kỳ ai :) điểm nằm trong 'chung' trong sự kiện - nếu bạn chỉ cần một tá sự kiện khác nhau, ok. Nhưng nếu bạn không biết trước bản chất của chữ T - chỉ được biết trong thời gian chạy - thì bạn cũng cần một sự kiện chung chung. Vì vậy, nếu bạn có một ứng dụng là một phần tốt để xử lý w / generics, số loại tùy ý, không xác định - thì bạn cũng cần các sự kiện chung. hoặc tức là không có giải pháp rõ ràng nào cho mọi vấn đề, quy tắc ngón tay cái chỉ là quy tắc ngón tay cái - và đó là ý của tôi đối với những người theo chủ nghĩa thuần túy, mỗi giải pháp đều khác nhau, bạn cần cân nhắc giữa những thứ, ưu và nhược điểm
NSGaga không hoạt động

2
Thiết kế không phải là màu đen và trắng, vì vậy tôi có xu hướng đồng ý với NSGaga ở đây. Đôi khi, "nhanh chóng và bẩn thỉu" là thích hợp. Ngôn ngữ phải giàu tính năng để phù hợp với hầu hết các trường hợp sử dụng. Nó sẽ tùy thuộc vào nhà phát triển để quyết định những gì phù hợp. Lần cuối cùng MS cố gắng ép buộc thiết kế "tốt" bằng cách hạn chế ngôn ngữ là WPF khi họ cố ép sử dụng XAML bằng cách vô hiệu hóa nghiêm trọng API .NET, và điều đó thật khủng khiếp.
Cướp

9

Nó tồn tại. Ít nhất, nó làm bây giờ.

Bạn có thể tìm thấy DataEventArgs<TData>trong một số tổ hợp / không gian tên khác nhau của Microsoft, chẳng hạn như Microsoft.Practices.Prism.Events . Tuy nhiên, đây là những không gian tên mà bạn có thể không thấy tự nhiên khi đưa vào dự án của mình, vì vậy bạn có thể chỉ sử dụng cách triển khai của riêng mình.


Tôi đang cố gắng tìm các đề xuất và cân nhắc về thời điểm và lý do sử dụng lớp EventArgs chung chung như vậy. Xem thêm: stackoverflow.com/questions/15766219/…
Ulf Åkerstedt

Dưới đây là một số khía cạnh để hãy cẩn thận khi quyết định sử dụng một EventArgs generic: stackoverflow.com/questions/129453/...
Ulf Åkerstedt

7

Trong trường hợp bạn chọn không sử dụng Prism , nhưng vẫn muốn thử cách tiếp cận EventArgs chung .

public class GenericEventArgs<T> : EventArgs
{
    public T EventData { get; private set; }

    public GenericEventArgs(T EventData)
    {
        this.EventData = EventData;
    }
}

// Sử dụng mã mẫu sau để khai báo sự kiện objAdded

public event EventHandler<GenericEventArgs<TargetObjType>> ObjAdded;

// Sử dụng mã mẫu sau để nâng cao sự kiện objAdded

private void OnObjAdded(TargetObjType TargetObj)
{
    if (ObjAdded!= null)
    {
        ObjAdded.Invoke(this, new GenericEventArgs<TargetObjType>(TargetObj));
    }
}

// Và finnaly bạn có thể đăng ký sự kiện ObjAdded của mình

SubscriberObj.ObjAdded +=  (object sender, GenericEventArgs<TargetObjType> e) =>
{
    // Here you can explore your e.EventData properties
};

3

KHÔNG CÓ THUỘC TÍNH THẾ HỆ NÀO TIỆN LỢI. Nếu bạn làm theo mẫu EventHandler của Microsoft, thì bạn triển khai EventArgs dẫn xuất của mình như bạn đã đề xuất: public class MyStringChangedEventArgs : EventArgs { public string OldValue { get; set; } } .

TUY NHIÊN - nếu hướng dẫn phong cách nhóm của bạn chấp nhận đơn giản hóa - dự án của bạn có thể sử dụng các sự kiện nhẹ, như sau:

public event Action<object, string> MyStringChanged;

sử dụng :

// How to rise
private void OnMyStringChanged(string e)
{
    Action<object, string> handler = MyStringChanged;    // thread safeness
    if (handler != null)
    {
        handler(this, e);
    }
}

// How to handle
myObject.MyStringChanged += (sender, e) => Console.WriteLine(e);

Thông thường các dự án PoC sử dụng cách tiếp cận thứ hai. Tuy nhiên, trong các ứng dụng chuyên nghiệp, hãy lưu ý biện minh cho cảnh sát FX # CA1009: https://msdn.microsoft.com/en-us/library/ms182133.aspx


1

Vấn đề với kiểu chung là ngay cả khi DerivedType kế thừa từ BaseType, EventArgs (DerivedType) sẽ không kế thừa từ EventArgs (BaseType). Do đó, việc sử dụng EventArgs (BaseType) sẽ ngăn việc sử dụng phiên bản dẫn xuất của loại sau này.


2
Điều này là sai nghiêm trọng. vui lòng xem "Covariance and Contravariance in Generics - Microsoft.com" msdn.microsoft.com/en-us/library/dd799517.aspx
Shaun Wilson

1
@ShaunWilson: Sai ở khía cạnh nào? Người ta có thể xác định một giao diện hiệp phương sai IEventArgs, nhưng các lớp duy nhất có thể là chung đối với các tham số kiểu chung là các đại biểu sẽ không được cung cấp Delegate.Combine. Các đại biểu sẽ được sử dụng với Delegate.Combinekhông được đồng biến, vì người ta có thể lưu trữ ví dụ: một Action<DerivedType>vào một trường kiểu Action<BaseType>, nhưng nỗ lực sau Combineđó với một trường hợp Action<BaseType>sẽ không thành công.
supercat

-4

Lý do điều này không tồn tại là bởi vì những gì cuối cùng sẽ xảy ra là bạn thực hiện điều này, và sau đó khi bạn điền vào chữ T, bạn nên tạo một lớp với các thuộc tính rõ ràng được nhập mạnh mẽ hoạt động như túi dữ liệu cho đối số sự kiện của bạn, nhưng Nửa chừng việc triển khai mà bạn nhận ra rằng không có lý do gì bạn không làm cho lớp đó kế thừa từ EventArgs và gọi nó là tốt.

Trừ khi bạn chỉ muốn một chuỗi hoặc một cái gì đó cơ bản tương tự cho túi dữ liệu của mình, trong trường hợp đó, có thể có tiêu chuẩn các lớp EventArgs trong .NET nhằm phục vụ bất kỳ mục đích đơn giản nào bạn đang làm.


-1. Tôi đã CHÍNH XÁC tình huống này ngay bây giờ và trọng tải của tôi sẽ là một đối tượng bất biến là "thông điệp" đến từ xe buýt ... và isu sed ở những nơi khác nữa. EventArgs tùy chỉnh .... tạo ra một lớp dư thừa ở đây. Không bình thường, nhưng ứng dụng là như vậy.
TomTom,
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.