.NET是否具有内置的EventArgs <T>?


84

我准备为带有单个参数的事件args创建通用的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>
Henk Holterman 2010年

1
您可能已经EventArgs<T>在基于CAB / SCSF的代码中看到过。在CAB / SCSF应用程序中很常见。虽然它不是框架的一部分,但是一个EventArgs <T>实现。
肖恩·威尔逊

Answers:


66

EventHandler<T>不会。您可能在考虑,它允许您为任何特定类型的EventArgs定义委托。

不过,我个人认为这EventArgs<T>不太合适。我认为,在事件args中用作“有效负载”的信息应该是一个自定义类,以使其用途和预期属性非常清楚。使用泛型类将阻止您将有意义的名称放到位。(“数据”代表什么?)


50
在以数据为中心,类似于MPI的应用程序中,很常见的情况是看到EventArgs <T>进行数据处理,以便开发人员可以利用内置的类型安全的订阅/注册系统(.NET事件和委托),因为创建EventArgs子类仅用于传输数据绝对没有意义。如果您打算传输数据,那么可以定义一个EventArgs <T>更为合理,您可以将其子类化以用于离散用途,而无需考虑传输的数据。TL:DR此答案的第一部分是真实准确的,第二部分是主观/观点。
肖恩·威尔逊

1
我想你是对的...抵制把我带到这里的懒惰。就像懒惰的开发人员使用Tuple <,>一样。糟糕的东西。
CRice 2014年

很好,但这实际上与Microsoft在将Tag属性添加到Controls类时所做的事情相同。当然,只是因为MS做到了,并没有做到正确。
肯·理查兹

1
我同意第一位评论者的意见,整个答案的后半部分是主观意见/代码宗教,但没有建设性。:(
BrainSlugs83

5
如何事件处理程序<客户>事件处理程序<订单>传达任何小于信息CustomerEventHandlerOrderEventHandler
Quarkly

33

我必须说我不了解这里的所有“纯粹主义者”。也就是说,如果您已经定义了bag类-其中包含所有详细信息,属性等-为什么hack会创建一个额外的不必要类,以便能够遵循事件/参数机制,签名样式?事情是-不是.NET中的所有内容-或为此而“遗失”-是“好”-MS多年来一直在“自我校正” ...我会说就去创建一个-就像我所做的那样-因为我就这样需要它-并节省了很多时间,


3
在这种情况下,“纯粹主义者”的目的是使意图尽可能清晰。在生产应用程序中,我有许多此类EventArgs类。从现在开始的一年后,如果我遵循Reed的建议并创建一个自定义EventArgs类,将会更容易理解我的工作。
David Veeneman

9
并不是要给任何人贴标签:)事件中的点是“通用”-如果您只需要一打不同的事件,就可以了。但是,如果您事先不了解T的性质(仅在运行时才知道),那么您就需要一个通用事件。因此,如果您的应用程序很好地处理了泛型,任意类型的未知类型,那么您还需要泛型事件。或即没有为每一个问题棱角分明的解决方案,经验法则仅仅是一个经验法则-这就是我的意思是由纯粹主义者,每个解决方案都是不同的,你需要权衡的事情,利弊
NSGaga-mostly-无效

2
设计不是黑白的,所以我倾向于在这里同意NSGaga。有时,“快而脏”是合适的。该语言应具有丰富的功能,以适合大多数用例。开发人员应自行决定合适的方法。MS上次通过限制语言来强制“良好”设计的尝试是WPF,当时他们试图通过严重限制.NET API来强制使用XAML,这很糟糕。
抢劫

9

它确实存在。至少现在可以了。

您可以DataEventArgs<TData>在一些不同的Microsoft程序集/命名空间中找到,例如Microsoft.Practices.Prism.Events。但是,这些名称空间可能不自然地包含在您的项目中,因此您可以只使用自己的实现。


我一直在寻找有关何时以及为何使用此类通用EventArgs类的建议和注意事项。参见:stackoverflow.com/questions/15766219/...
乌尔夫Åkerstedt

这里有一些方面要提防在使用通用的EventArgs决定时:stackoverflow.com/questions/129453/...
乌尔夫Å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

没有内置的一般商品。如果遵循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 cop证明#CA1009:https ://msdn.microsoft.com/zh-cn/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>到type的字段中Action<BaseType>,但是以后尝试Combine使用的实例Action<BaseType>将失败。
2013年

-4

之所以不存在,是因为最终实现是因为您实现了它,然后当您填写T时,您应该创建一个具有强类型明确属性的类,该类充当事件arg的数据包,但是在实现的过程中,您意识到没有理由不只是让该类从EventArgs继承并称其为好。

除非您只希望为数据包使用字符串或类似的基本内容,否则在这种情况下,.NET中可能存在EventArgs类标准,这些标准旨在满足您所达到的任何简单目的。


-1。我现在已经完全是这个姿势了,我的有效载荷将是一个不变的对象,它是来自公共汽车的“消息”……并在其他地方被发出。自定义EventArgs ....在此处创建一个冗余类。不寻常,但应用程序是如此。
TomTom
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.