将委托转换为系统操作



简介

在我的 WP8 C#/XAML 项目中,我使用事件来通知我的视图某些异步过程已完成。

我有两种类型的代表。

正在从这些委托创建事件,其中有几个通知我的观点某些操作已完成或启动(为了显示进度条,导航到另一个页面,禁用一些控件等)。

为了引发这些

事件,我想创建一个私有的"通知方法",这将引发这些委托。

我想到的方法在下面的代码示例中作为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();
  }
}

用法

fireUpEvent(LoadingFinished, ReturnState.state1);

描述

问题是,当我尝试编译时,我收到一个错误,说:

Argument1: Cannot convert from 'XXXX.YYYY.SomeClass.LoadingFinishedEventHandler' to 'System.Action<XXXX.YYYY.Returnstate>'

我尝试过谷歌搜索,但没有找到任何有用的东西。

为什么它不可转换?

我想用这些方法而不是特定的代表来Action<ReturnState>Action,这可能吗?

我应该使用任何其他"类型",如Action吗?

我从这个"槽"中知道的唯一两个是Func&Action,还有其他人吗?

要回答这一行:

为什么它不可转换?

它们是不同的委托类型,并且不同委托类型之间没有引用转换(使用通用方差的通用委托类型除外)。您可以从如下所示的LoadingStartedEventHandler创建Action

LoadingStartedEventHandler handler = ...; // Whatever
Action action = new Action(handler);

。你可以反过来做同样的事情,用你的其他委托类型和Action<T>。但真的没有必要这样做。

我想用这些方法而不是特定的代表来Action<ReturnState>Action,可能吗?

是的 - 只是不要使用这些委托声明事件,实际上根本不声明委托!

您可以更改此设置:

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;

请注意,这违反了有关事件的 .NET 约定。按照惯例,事件是使用委托声明的,其中第一个参数是类型为 object 的"发送者",第二个参数是从 EventArgs(或EventArgs本身)派生的类型。这对你来说是否重要是由你决定的。如果您决定遵循约定,则基本上希望创建一个从持有ReturnState EventArgs派生的类型,然后将事件替换为:

public event EventHandler LoadingStarted;
public event EventHandler<ReturnStateEventArgs> 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);
  }
}

(我修改了方法名称以遵循 .NET 约定,并对事件使用 .NET 术语,这些事件是"引发"而不是"启动"。

斯基特先生总是能做出很好的答案。在这里,我提供了您在问题中所说的另一种解决方案。

对于这两个:

  1. 为什么它不可转换?
  2. 我想在这些方法中操作和操作而不是特定的代表,可以吗?

斯基特先生已经回答了。

对于这两个:

  1. 我应该改用任何其他"类型",如操作吗?
  2. 我从这个"grooup"中知道的唯一两个是Func和Action,还有其他的吗?

您的fireUpEvent方法可能不应接受 arbrary 类型的委托作为脆性设计。但这是可能的。

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是拥有该方法的对象,如果它是静态方法,null将被视为thisargs是传递给方法的参数列表。

这只是你可以实现它的一种方式,我很确定斯基特先生的答案绝对更好。

相关内容

  • 没有找到相关文章

最新更新