.NET에는 기본 제공 EventArgs <T>가 있습니까?


84

단일 인수를 전달하는 이벤트 인수에 대한 일반 EventArgs 클래스를 만들 준비가되었습니다.

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; }
    }
}

그렇게하기 전에 C #에는 언어에 동일한 기능이 내장되어 있습니까? C # 2.0이 나왔을 때 그런 일을 겪었던 것을 기억하는 것 같지만 지금은 찾을 수 없습니다.

또는 다른 방법으로 말하면 고유 한 제네릭 EventArgs 클래스를 만들어야합니까, 아니면 C #에서 제공합니까? 당신의 도움을 주셔서 감사합니다.


9
당신은 Eventhandler<T>
보셨을 것입니다

1
당신은 볼 수도 EventArgs<T>CAB / SCSF 기반 코드. CAB / SCSF 응용 프로그램에서 매우 일반적입니다. 이 프레임 워크의 일부가 아니지만, 거기에 있다 있는 EventArgs <T> 구현입니다.
Shaun Wilson

답변:


66

아니요 EventHandler<T>. 특정 유형의 EventArgs에 대한 대리자를 정의 할 수있는를 생각했을 것입니다 .

나는 개인적으로 그것이 EventArgs<T>적합 하다고 생각하지 않습니다 . 이벤트 인수에서 "페이로드"로 사용되는 정보는 사용 및 예상 속성을 매우 명확하게 만드는 사용자 정의 클래스 여야합니다. 제네릭 클래스를 사용하면 의미있는 이름을 제자리에 넣을 수 없습니다. ( "데이터"는 무엇을 의미합니까?)


50
데이터 중심의 MPI와 유사한 응용 프로그램에서는 개발자가 내장 된 형식 안전 구독 / 등록 시스템 (.NET 이벤트 및 대리자)을 활용할 수 있도록 데이터 처리를 위해 EventArgs <T>를 보는 것이 일반적입니다. 데이터를 전송하기 위해 EventArgs 하위 클래스를 만드는 것은 전혀 의미가 없습니다. 데이터를 전송하려는 경우 EventArgs <T>를 정의하는 것이 더 합리적입니다. 전송되는 데이터에 관계없이 개별 용도로 하위 클래스를 만들 수 있습니다. TL : DR이 답변의 첫 번째 부분은 사실적이고 정확하며 두 번째 부분은 주관적 / 의견입니다.
Shaun Wilson

1
당신 말이 맞다고 생각합니다 ... 나를 여기에 데려온 게으름에 저항하십시오. 게으른 개발자가 Tuple <,>을 사용하는 것과 같습니다. 끔찍한 것들.
CRice

좋은 지적이지만 이것은 본질적으로 Microsoft가 Controls 클래스에 Tag 속성을 추가했을 때와 동일한 작업을 수행하는 것입니다. 물론, 그냥 coz 'MS가 해냈지만 옳지 않습니다.
Ken Richards

1
나는 첫 번째 해설자에 동의하며,이 답변의 후반부는 건설적이지 않은 주관적인 의견 / 규범 종교입니다. :(
BrainSlugs83

5
EventHandler <Customer> 또는 EventHandler <Order>CustomerEventHandler 또는 OrderEventHandler 보다 적은 정보를 어떻게 전달 합니까?
Quarkly

33

나는 여기서 모든 '순수 주의자'를 이해하지 못한다고 말해야한다. 즉, 모든 세부 사항, 속성 등을 포함하는 가방 클래스가 이미 정의되어있는 경우 해킹이 이벤트 / 인수 메커니즘, 서명 스타일을 따를 수 있도록 하나의 불필요한 클래스를 추가로 만드는 이유는 무엇입니까? 문제는-.NET에있는 모든 것이 아니라-또는 그 문제에 대해 '누락 된'것이 아닙니다- '좋은 것'입니다-MS는 수년 동안 스스로를 '수정'해 왔습니다. -저도 그렇게 필요했기 때문에-많은 시간을 절약했습니다.


3
이 경우 '순수 주의자'의 요점은 의도를 최대한 명확하게하는 것입니다. 프로덕션 앱에는 이러한 EventArgs 클래스가 수십 개 있습니다. 지금부터 1 년 후 Reed의 조언을 따르고 사용자 지정 EventArgs 클래스를 만들면 내가 한 일을 이해하는 것이 더 쉬울 것입니다.
David Veeneman 2011 년

9
누구에게도 레이블을 지정하려는 것이 아닙니다. :) 이벤트의 '일반'에있는 포인트입니다. 12 개의 다른 이벤트 만 필요하면 좋습니다. 그러나 T의 특성을 미리 알지 못한다면 (런타임에만 알려진 것입니다) 글쎄요, 일반적인 이벤트가 필요합니다. 따라서 제네릭, 알 수없는 임의의 유형 수를 처리하는 좋은 앱이있는 경우 제네릭 이벤트도 필요합니다. 또는 즉, 모든 문제에 대한 깔끔한 해결책이 없습니다. 경험 법칙은 단지 경험 법칙입니다. 이것이 제가 순수 주의자들이 의미하는 바입니다. 각 솔루션은 서로 다르며, 장단점을 평가해야합니다
NSGaga- 대부분- 비활성

2
디자인은 흑백이 아니므로 여기서 NSGaga에 동의하는 경향이 있습니다. 때로는 "빠르고 더럽다"가 적절합니다. 언어는 대부분의 사용 사례에 적합하도록 기능이 풍부해야합니다. 무엇이 적절한 지 결정하는 것은 개발자의 몫입니다. MS가 언어를 제한하여 "좋은"디자인을 강제로 시도한 것은 .NET API를 심각하게 핸디캡으로 처리하여 XAML 사용을 강제하려고 할 때 WPF였습니다. 끔찍했습니다.
Robear

9

존재합니다. 적어도 지금은 그렇습니다.

DataEventArgs<TData>예를 들어 Microsoft.Practices.Prism.Events 와 같은 일부 다른 Microsoft 어셈블리 / 네임 스페이스에서 찾을 수 있습니다 . 그러나 이들은 프로젝트에 포함하는 것이 자연스럽지 않은 네임 스페이스이므로 자체 구현을 사용할 수 있습니다.


이러한 일반 EventArgs 클래스를 사용하는시기와 이유에 대한 권장 사항과 고려 사항을 찾으려고 노력해 왔습니다. 참조 : stackoverflow.com/questions/15766219/...
울프 Åkerstedt

다음은 일반 EventArgs 사용을 결정할 때주의해야 할 몇 가지 측면입니다. stackoverflow.com/questions/129453/…
Ulf Åkerstedt

7

Prism 을 사용하지 않기로 선택 했지만 여전히 일반적인 EventArgs 접근 방식 을 시도하려는 경우 .

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

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

// 다음 샘플 코드를 사용하여 ObjAdded 이벤트 를 선언합니다.

public event EventHandler<GenericEventArgs<TargetObjType>> ObjAdded;

// 다음 샘플 코드를 사용하여 ObjAdded 이벤트를 발생 시킵니다.

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

// 그리고 마지막으로 ObjAdded 이벤트를 구독 할 수 있습니다.

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

3

내장 된 일반 ARGS가 없습니다. Microsoft EventHandler 패턴을 따르는 경우 제안한대로 파생 된 EventArgs를 구현합니다 public class MyStringChangedEventArgs : EventArgs { public string OldValue { get; set; } }..

그러나-팀 스타일 가이드가 단순화를 허용하는 경우 프로젝트는 다음과 같은 간단한 이벤트를 사용할 수 있습니다.

public event Action<object, string> MyStringChanged;

사용법 :

// 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);

일반적으로 PoC 프로젝트는 후자의 접근 방식을 사용합니다. 그러나 전문 응용 프로그램의 경우 FX 경찰 정당화 # CA1009에 유의하십시오 : https://msdn.microsoft.com/en-us/library/ms182133.aspx


1

제네릭 형식의 문제는 DerivedType이 BaseType에서 상속하더라도 EventArgs (DerivedType)가 EventArgs (BaseType)에서 상속되지 않는다는 것입니다. 따라서 EventArgs (BaseType)을 사용하면 나중에 파생 된 형식의 버전을 사용할 수 없습니다.


2
이것은 명백히 거짓입니다. "공분산 및 제네릭의 반공 변성-Microsoft.com" msdn.microsoft.com/en-us/library/dd799517.aspx
Shaun Wilson

1
@ShaunWilson : 어떤 측면이 거짓입니까? 하나는 공변 인터페이스를 정의 할 수 IEventArgs있지만 제네릭 형식 매개 변수와 관련하여 제네릭이 될 수있는 유일한 클래스는 공급되지 않는 대리자입니다 Delegate.Combine. 와 함께 사용할 델리게이트는 Delegate.Combine공변 적이 어서는 안됩니다. 예를 들어 Action<DerivedType>를 유형 필드에 저장할 수 Action<BaseType>있지만 나중에 Combine인스턴스를 사용하여 시도 Action<BaseType>하면 실패합니다.
supercat

-4

이것이 존재하지 않는 이유는 결국 이것을 구현하고 T를 채울 때 이벤트 인수에 대한 데이터 백 역할을하는 강력한 유형의 명확한 속성을 가진 클래스를 만들어야하기 때문입니다. 구현 중간에 해당 클래스를 EventArgs에서 상속하도록 만들고이를 good이라고 부르지 않을 이유가 없다는 것을 알게되었습니다.

데이터 백에 대해 문자열이나 이와 유사한 기본적인 것을 원하지 않는 한,이 경우 .NET에있는 EventArgs 클래스 표준이있을 것입니다.


-1. 나는 지금 정확히이 상황을 가지고 있고, 내 페이로드는 버스에서 오는 "메시지"인 불변의 객체가 될 것이고 다른 곳에서도 전송 될 것이다. 사용자 지정 EventArgs ....는 여기에 중복 클래스를 만듭니다. 비정상적이지만 응용 프로그램은 그렇습니다.
TomTom
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.