C# 将委托转换为System.Action 介绍
在我的wp8c#/XAML项目中,我使用事件通知我的视图某些异步过程已经完成 我有两类代表 我正在从这些代理创建事件,其中有几个代理通知我的视图某些操作已完成或启动(为了显示progressbar、导航到另一个页面、禁用某些控件等等) 为了引发这些事件,我想创建一个私有的“通知方法”,它将引发这些委托 我想到的方法在下面的代码示例中是C# 将委托转换为System.Action 介绍,c#,windows-phone-8,event-handling,C#,Windows Phone 8,Event Handling,在我的wp8c#/XAML项目中,我使用事件通知我的视图某些异步过程已经完成 我有两类代表 我正在从这些代理创建事件,其中有几个代理通知我的视图某些操作已完成或启动(为了显示progressbar、导航到另一个页面、禁用某些控件等等) 为了引发这些事件,我想创建一个私有的“通知方法”,它将引发这些委托 我想到的方法在下面的代码示例中是fireUpEvent方法 代码示例 返回状态枚举 public enum ReturnState : int { state1 = 0, ...
fireUpEvent
方法
代码示例
返回状态枚举
public enum ReturnState : int
{
state1 = 0,
... //for the purpose of the presentation
state6 = 15
...
}
事件和方法的定义
public delegate void LoadingStartedEventHandler();
public delegate void LoadingFinishedEventHandler(ReturnState state);
public event LoadingStartedEventHandler LoadingStarted;
public event LoadingFinishedEventHandler LoadingFinished;
private void fireUpEvent(Action<ReturnState> action, Returnstate parameter)
{
if(action != null)
{
action(parameter);
}
}
private void fireUpEvent(Action action)
{
if(action != null)
{
action();
}
}
描述
问题是,当我尝试编译时,会出现一个错误,错误是:
Argument1:无法从'XXXX.yyy.SomeClass.LoadingFinishedEventHandler'转换为'System.Action'
我试过谷歌搜索,但没有找到任何有用的东西
为什么不能兑换?
我想在这些方法中而不是在特定的代表中执行操作
和操作
,有可能吗?
我是否应该使用任何其他“类型”,如操作
?
我从这个“群组”中只知道两个是Func
和Action
,还有其他的吗?回答这一行:
为什么它不能兑换
它们是不同的委托类型,不同委托类型之间不存在引用转换(使用泛型差异的泛型委托类型除外)。您可以从LoadingStartedEventHandler
创建操作,如下所示:
LoadingStartedEventHandler handler = ...; // Whatever
Action action = new Action(handler);
。。。你也可以反过来做同样的事情,用你的其他委托类型和动作
。但真的没有必要这么做
我想在这些方法中使用操作
和操作
,而不是特定的委托,是否可能
是的-只是不要使用这些委托声明事件,实际上根本不要声明委托
您可以更改此设置:
public delegate void LoadingStartedEventHandler();
public delegate void LoadingFinishedEventHandler(ReturnState state);
public event LoadingStartedEventHandler LoadingStarted;
public event LoadingFinishedEventHandler LoadingFinished;
为此:
public event Action LoadingStarted;
public event Action<ReturnState> LoadingFinished;
并将助手方法更改为:
private void RaiseEvent(EventHandler<TEventArgs> handler,
TEventArgs parameter)
{
if(handler != null)
{
handler(this, parameter);
}
}
private void RaiseEvent(EventHandler handler)
{
if(handler != null)
{
handler(this, EventArgs.Empty);
}
}
private void RaiseEvent(事件处理程序,
TEventArgs参数)
{
if(处理程序!=null)
{
handler(这个参数);
}
}
私有void RaiseEvent(事件处理程序)
{
if(处理程序!=null)
{
处理程序(此,EventArgs.Empty);
}
}
(我修改了方法名称,使之符合.NET约定,并使用.NET术语来表示事件,这些事件是“引发的”,而不是“激发的”。斯基特先生总是能给出很好的答案。在这里,我提供了你在问题中所说的另一个解决方案
对于这两位:
为什么它不能兑换李>
我想在这些方法中采取行动,而不是具体的代表,这可能吗
斯基特先生已经回答了
对于这两位:
我应该使用其他类型的动作来代替吗
从这个“grooup”中我只知道两个是Func&Action,还有其他的吗
您的fireUpEvent
方法可能不应接受任意类型的委托作为脆弱的设计。但这是可能的
C#中所有委托类型的最终基类型是delegate
;Delegate
的一个限制是它不能是泛型类型和方法中的where
约束
要回答这个问题(无论设计如何),您可以说:
private void fireUpEvent(
Delegate loadingEvent, ReturnState? parameter=null) {
if(null!=loadingEvent) {
foreach(var d in loadingEvent.GetInvocationList()) {
var args=null!=parameter?new object[] { parameter }:null;
d.Method.Invoke(d.Target, args);
}
}
}
如果是静态方法,Target
是拥有该方法的对象,则将其视为this
,null
,而不是问题中最初的两个方法args
是传递给方法的参数列表
这只是一种实现它的方法,我敢肯定斯基特先生的答案绝对是更好的 这确实是一个很好的答案,提醒大家注意这些惯例。我不知道。有时候很难找到一个完整的答案来解释原因。很多教程只是以“像这样做,我就是这样做的”的方式展示内容,而没有进一步解释为什么要这样做。这就是为什么你的答案是宝石。谢谢,谢谢你的意见。我已经修改了我的代码以使用EventHandler和我的EventArgs派生版本,这最终比我拥有的第一个解决方案短。我只是从来没有学到很多关于事件的知识,以及如何正确地使用它,这就是为什么我首先问这个问题的原因。我很高兴了解更多+1.
private void RaiseEvent(EventHandler<TEventArgs> handler,
TEventArgs parameter)
{
if(handler != null)
{
handler(this, parameter);
}
}
private void RaiseEvent(EventHandler handler)
{
if(handler != null)
{
handler(this, EventArgs.Empty);
}
}
private void fireUpEvent(
Delegate loadingEvent, ReturnState? parameter=null) {
if(null!=loadingEvent) {
foreach(var d in loadingEvent.GetInvocationList()) {
var args=null!=parameter?new object[] { parameter }:null;
d.Method.Invoke(d.Target, args);
}
}
}