如何在EventArgs中传递对象

问题描述 投票:0回答:5

我有一个用户控件,它在与 Web 服务通信后引发一个事件。父级在引发时处理此事件。我认为正确的方法是将 Web 服务返回的对象作为 eventargs 传递给父级??? 如果这是正确的方法,我似乎找不到有关如何操作的说明。

用户控制

public event EventHandler LoginCompleted;
然后在服务返回 biz 对象之后:

if (this.LoginCompleted != null) { // This is where I would attach / pass my biz object no? this.LoginCompleted(this, new EventArgs()); }

家长

ctrl_Login.LoginCompleted += ctrl_Login_LoginCompleted; ....snip.... void ctrl_Login_LoginCompleted(object sender, EventArgs e) { // Get my object returned by login }
所以我的问题是,将用户对象返回给父级的“批准”方法是什么?创建一个所有东西都可以访问的属性类并将其放在那里?

c# eventargs
5个回答
50
投票
EventHandler<T>

声明您的事件,其中

T
是派生自
EventArgs
的类:

public event EventHandler<LoginCompletedEventArgs> LoginCompleted;

LoginCompletedEventArgs

可能看起来像这样:


public class LoginCompletedEventArgs : EventArgs { private readonly YourBusinessObject _businessObject; public LoginCompletedEventArgs(YourBusinessObject businessObject) { _businessObject = businessObject; } public YourBusinessObject BusinessObject { get { return _businessObject; } } }

用法如下:

private void RaiseLoginCompleted(YourBusinessObject businessObject) { var handler = LoginCompleted; if(handler == null) return; handler(this, new LoginCompletedEventArgs(businessObject)); }

请注意我是如何实现的
RaiseLoginCompleted

。这是引发事件的线程安全版本。我消除了在竞争条件场景中可能发生的

NullReferenceException
,其中一个线程想要引发事件,而另一个线程在
if
检查之后但在实际调用处理程序之前取消订阅最后一个处理程序。
    


14
投票

如:

public delegate void MyEventEventHandler(int prop1, string prop2, object prop3...); public event MyEventEventHandler MyEvent;



6
投票
命名元组

EventHandler<TEventArgs>


我喜欢olddog的

答案

。 Microsoft 已经有了这个委托 EventHandler。< TEventArgs > public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);

您不需要继承
EventArgs


使用命名元组声明您的事件处理程序。

public event EventHandler<(int id, string message, object LoginObject)> LoginCompleted;

在您的客户端代码中,将方法分配给 LoginCompleted 事件处理程序

选项 1:使用 lambda

LoginCompleted += (o, e) => { Console.WriteLine($"Hello, sender is {o.ToString()}! id is {e.id}, message is {e.message}, and LoginObject is {e.LoginObject.ToString()}. "); };

选项 2:调用本地方法 

LoginCompleted += onLoginCompleted; private static void onLoginCompleted (object sender, (int id, string message, object LoginObject) e) { Console.WriteLine($"Hello, sender is {sender.ToString()}! id is {e.id}, message is {e.message}, and LoginObject is {e.LoginObject.ToString()}. "); }

我只是写了一个例子,请参考我的
repo


5
投票
https://coderwall.com/p/wkzizq/generic-eventargs-class

)。它与接受的答案不同,因为您不必创建特殊的 EventHandler 类(例如 LoginCompletedEventArgs)。


注意

:我使用的是 VS 2015 和 C# v6。在旧版本的 Visual Studio 和 C# 中,您可能需要添加 using System.Linq;


创建一个继承自 EventArgs 的通用 EventArgs

... class EventArgs<T> : EventArgs { public T Value { get; private set; } public EventArgs(T val) { Value = val; } }

声明您的事件处理程序
...

public event EventHandler<EventArgs<object>> LoginCompleted;

假设您已声明并分配了一个名为 
loginObject

的对象,请添加代码以引发事件

...
private void RaiseLoginCompleted() { if (LoginCompleted != null) LoginCompleted(this, new EventArgs<object>(loginObject)); }

在您的客户端代码中,添加 
LoginCompleted

事件处理程序(使用 Linq 并调用本地方法)

...
LoginCompleted += (o, e) => onLoginCompleted(e.Value); // calls a local method void onLoginCompleted(LoginObject obj) { // add your code here }



3
投票
EventArgs

,这很糟糕!所以你可以简单地使用

Action
而不是
EventHandler
。您可以传递任何类型和您喜欢的参数数量(Action 最多支持 16 个)。

class Raiser { public event Action<Raiser, bool,DateTimeOffset> OnCreate; public void Create() { OnCreate?.Invoke(this, true,DateTimeOffset.Now); } } class Listener { Raiser raiser; public Listener() { raiser = new Raiser(); raiser.OnCreate += Raiser_OnCreate; } private void Raiser_OnCreate(Raiser arg1, bool arg2,DateTimeOffset dateTimeOffset) { throw new NotImplementedException();//Do Your works here } }

通常使用 
Action

和 'Func' 比

Delegate
更容易。
    

© www.soinside.com 2019 - 2024. All rights reserved.