C# 使另一个类中的方法在调用该类时调用该类中的事件';结束了吗?

C# 使另一个类中的方法在调用该类时调用该类中的事件';结束了吗?,c#,events,windows-phone-7,delegates,C#,Events,Windows Phone 7,Delegates,我需要开始下载一些html,所以我在另一个类中调用void GetHTML。当它完成时,我想传递它应该在调用类中引发的事件。我怎么能这样做 所以它看起来像这样: public class Stuff { public void GetHTML(string url, event to raise here) { //Do stuff then raise event } } public class Other { public Other()

我需要开始下载一些html,所以我在另一个类中调用void GetHTML。当它完成时,我想传递它应该在调用类中引发的事件。我怎么能这样做

所以它看起来像这样:

public class Stuff
{
    public void GetHTML(string url, event to raise here)
    {
       //Do stuff then raise event
    }
}
public class Other
{
    public Other()
    {
        Stuff stuff = new Stuff();
        stuff.GetHTML(someUrl, somehow sending info that HTML_Done should be called);
    }
    void HTML_Done(string result, Event e)
    {
         //Do stuff with the result since it's done
    }
}
我意识到我不太清楚我想做什么,我很乐意填补任何缺失的部分


谢谢你的建议

我不确定这是否是您想要的,但您可以使用内置的
操作
委托类型:

public class Stuff
{
  public void GetHTML(string url, Action<string, Event> callback)
  {
     //Do stuff 

     //raise event
     callback("result here", new Event());       
  }
}

stuff.GetHTML(someUrl, HTML_Done);
公共类的东西
{
public void GetHTML(字符串url,操作回调)
{
//做事
//升起事件
回调(“result here”,new Event());
}
}
GetHTML(someUrl,HTML\u Done);

或者,使用和
EventHandler
委托类型。您需要创建自己的
EventArgs
类型。

如果我没有看错您的话。我想您应该这样做

public class Stuff 
{
     public void GetHTML(string url, event to raise here)
     {
        //Do stuff  and instead of raising event here
     }
 } 
public class Other
 {
     public Other()
     {
         Stuff stuff = new Stuff();
         stuff.GetHTML(someUrl, somehow sending info that HTML_Done should be called);
         //Raise event here once that method is finished
     }
     void HTML_Done(string result, Event e)
     {
          //Do stuff with the result since it's done
     }
 } 
你要回电话

public class Stuff
{
    public void GetHTML(string url, Action callback)
    {
       // Do stuff

       // signal we're done 
       callback();
    }
}

public class Other
{
    public Other()
    {
        Stuff stuff = new Stuff();

        // using a lambda callback
        stuff.GetHTML(someUrl, ()=> Console.WriteLine("Done!") );
        // passing a function directly
        stuff.GetHTML(someUrl, MyCallback);
    }

    public void MyCallback() 
    {
        Console.WriteLine("Done!");
    }
}
如果要传递参数,请适当地定义操作,即<代码>操作,然后回调变为
回调(“某些字符串”)

另一个选项是使用事件。看起来这就是你问这个问题的目的。我不推荐它,回调选项在我看来更好。不过,作为将来的参考,这是在这种情况下使用事件的方式

public delegate void DoneEventHandler(object sender, string result);

public class Stuff
{
    public event DoneEventHandler DoneEvent = delegate {}; // avoid null check later

    public void GetHtml(string url)
    {
        // do stuff
        DoneEvent(this, "result");
    }
}

public class Other
{
    public void SomeMethod()
    {
        Stuff stuff = new Stuff();
        stuff.DoneEvent += OnDone;
        stuff.GetHtml(someUrl)
    }

    public void OnDone(objects sender, string result)
    {
        Console.WriteLine(result);
    }
}
有关如何使用的信息

事件订阅和通知

使用此模式允许更多的订阅者

您也不会将通知程序
Stuff
类绑定到调用方
Other

你要么有订阅者,要么没有订阅者,这与
Stuff
类没有区别

Stuff
类不应该知道订阅者的情况,它应该只引发一个它公开的事件以供订阅

编辑
正如ctacke在注释中正确指出的,使用
this.GetHtmlDone(this,new EventArgs())引发事件将导致异常。
我更改了上面的代码,以确保通过初始化eventhandler随时安全引发事件。
由于我一直在使用它(通过提高它),我确信总是初始化你正在使用的东西是唯一好的做法

我本可以在事件处理程序上添加一个空检查,但在我个人的观点中,我不同意必须由
stuff
类负责。我觉得这件事应该一直提出来,因为这是一件“负责任的”事情

我发现了这一点,这向我证实了这样做似乎没有错

此外,我还对该代码进行代码分析,以确保初始化EventHandler不会违反CA1805规则。CA1805没有提出,也没有违反任何规则

用我在评论中的汽车类比,我相信不初始化eventhandler并一直提高它与说“当你的汽车转弯时,只有在有人在看的情况下才使用你的指示器,如果没有,就不用麻烦了”是一样的。你永远不知道是否有人在看,所以你最好确保你一直都在看

这只是我个人的喜好。其他人,请添加!=如果您希望这样做,请随时进行空检查

非常感谢您的评论和指出这一点。我从中学到了很多。

我现在必须回到我的一些项目,更新一些代码,以确保如果没有人订阅我的活动,我的库不会崩溃。在我的任何测试中都没有发现这一点,我觉得很傻。


你可以试试这种方法

public class Stuff
{
     public delegate void DownloadComplete("you can pass whatever info you like here");
     public event DownloadComplete OnDownloadComplete;
     public void GetHtml(string UrlToDownload)
     {
         //Download the data here
         //After data download complete
         if(OnDownloadComplete)
            OnDownloadComplete("arguments to be passed");
     }

} public class Other { public Other() { Stuff myStuff=new Stuff(); myStuff.OnDownloadComplete+=new EventHandler(myStuff_OnDownloadComplete); }

 void myStuff_OnDownloadComplete("arguments will be passed here")
 {
    //Do your stuff
 }
}

假设对GetHTML的调用是同步的。不必如此。为什么要使用
操作
?一个简单的
动作
更清晰、更充分。OP的HTML_Done签名包含一个事件类型,我想他希望包含该类型。这个假设是基于这个问题的模棱两可性。@dev,我假设他在签名中包含了这个事件,因为他假设需要一个事件。是的,我也想到了这种可能性,但我选择不假设他们对此一无所知。这是我不知道的。我更难过的是,他们的方法名称中有下划线,并且没有显式的访问修饰符。您甚至可以将EventArg设置为自定义EventArg,将重要信息传递给订阅者。尽管您应该仅在订阅者有订阅者的情况下调用
GetHtmlOne
,但无论订阅情况如何,我都会引发GetHtmlOne事件。
Stuff
类不负责检查订阅。
Stuff
类对订阅者没有依赖性。订阅服务器依赖于正在引发的事件。打个比方,我觉得这就像在转弯时在车里用指示器一样。我总是这样做,即使没有人在看(订阅)。我不依赖于我后面的车观看我使用指示器,但是,我后面的车依赖于我指示(提升我的事件)。至少我是这么看的。当然,
Other
添加了一个处理程序,所以你现在所拥有的可以工作,但是如果代码被重构或共享,而其他人使用
东西
,但没有连接GetHtmlDone,那么对this.GetHtmlDone的调用将抛出一个NullReferenceException。不要为手头的问题编写代码,而是为其他人在你不看的时候可能会做的事情编写代码。不确定你的意思,因为
stuff
永远不会引发异常。也许我遗漏了一些东西,但是无论是否订阅,任何东西都可以引用
东西。如果我遗漏了什么,很抱歉。我对你所说的“如何”很感兴趣,因为我完全支持防止异常。

public class Stuff
{
     public delegate void DownloadComplete("you can pass whatever info you like here");
     public event DownloadComplete OnDownloadComplete;
     public void GetHtml(string UrlToDownload)
     {
         //Download the data here
         //After data download complete
         if(OnDownloadComplete)
            OnDownloadComplete("arguments to be passed");
     }

} public class Other { public Other() { Stuff myStuff=new Stuff(); myStuff.OnDownloadComplete+=new EventHandler(myStuff_OnDownloadComplete); }

 void myStuff_OnDownloadComplete("arguments will be passed here")
 {
    //Do your stuff
 }