如何创建一个接收动态函数作为参数的函数?

How to create a function that receives as a parameter a dynamic function?

我正在 xamarin.android 中创建一个动态对话框,我希望该对话框接收一个函数,该函数将在单击操作按钮时执行。

这是我的代码:

public static void ShowDialogBox(Context context, Function dynamicFunction)
{
    Dialog popupDialog = new Dialog(context);
    popupDialog.SetContentView(Resource.Layout.dialog_dynamic);
    popupDialog.Window.SetSoftInputMode(SoftInput.AdjustResize);
    popupDialog.Window.SetBackgroundDrawableResource(Android.Resource.Color.Transparent);
    popupDialog.Show();

    TextView title = popupDialog.FindViewById<TextView>(Resource.Id.dialog_title);
    TextView content = popupDialog.FindViewById<TextView>(Resource.Id.dialog_content);
    ImageView icon = popupDialog.FindViewById<ImageView>(Resource.Id.dialog_icon);
    Button actionButton = popupDialog.FindViewById<Button>(Resource.Id.dialog_action_button);

    popupDialog.FindViewById<ImageButton>(Resource.Id.dialog_close).Click += delegate { popupDialog.Dismiss(); };
    popupDialog.FindViewById<Button>(Resource.Id.dialog_cancel_button).Click += delegate { popupDialog.Dismiss(); };
    
    actionButton.Click += dynamicFunction;
}

*请注意,Function 参数只是一个示例。另外我会把这个对话框中的文字和内容作为一个参数。

示例场景:

  1. 如果我将 GetCurrentDate 函数发送到此对话框,单击操作按钮时它将获取当前日期。
  2. 如果我向这个对话框发送 OpenBluetooth 函数,当点击操作按钮时它会打开蓝牙

单击操作按钮时,可以向此 ShowDialogBox 函数和 运行 发送另一个函数吗?我的目的是让我的代码简洁易用。

正如@Nico 已经评论的那样,您可以使用 Func 或委托作为参数。我建议您改用 Action

Xamarin.Forms.Button 上的 Clicked event 使用带有签名 void OnClicked(object? sender, EventArgs e) 的事件处理程序。因此,您的签名将使用 Action<object?, EventArgs> 参数。

有几点需要注意:

  • 如果您不在项目中使用可空引用类型,请省略问号
  • 您需要检查 null 的参数,然后再将其分配给 Clicked 事件
  • 调用 Action 不会 return 任何东西。如果你想“获取当前日期”,你的动作必须在字段或控件中写入当前日期
  • 如果你的函数需要其他参数,你需要传递一个委托(或者用sendere参数将你的函数调用包装在一个函数中:ShowDialogBox(context, (sender, e) => MyFunction("other data"))

面向对象可以帮助你:你可以将你的功能抽象成一个class,然后派生任何特定的功能class来实现你的特定动作。 类似于以下内容:

abstract class ActionClassBase
{
    public abstract void Action();

    private string data = "";
    public string Data { get { return data; } set { data = value; } }
}

class GetCurrentDateAction : ActionClassBase
{
    public override void Action()
    {
        Data = DateTime.Now.ToString();
    }
}

class OpenBlueToothAction : ActionClassBase
{
    public override void Action()
    {
        Data = "BlueTooth opened";
    }
}


public static void ShowDialogBox(Context context, ActionClassBase action)
{
    Dialog popupDialog = new Dialog(context);
    popupDialog.SetContentView(Resource.Layout.dialog_dynamic);
    popupDialog.Window.SetSoftInputMode(SoftInput.AdjustResize);
    popupDialog.Window.SetBackgroundDrawableResource(Android.Resource.Color.Transparent);
    popupDialog.Show();

    TextView title = popupDialog.FindViewById<TextView>(Resource.Id.dialog_title);
    TextView content = popupDialog.FindViewById<TextView>(Resource.Id.dialog_content);
    ImageView icon = popupDialog.FindViewById<ImageView>(Resource.Id.dialog_icon);
    Button actionButton = popupDialog.FindViewById<Button>(Resource.Id.dialog_action_button);

    popupDialog.FindViewById<ImageButton>(Resource.Id.dialog_close).Click += delegate { popupDialog.Dismiss(); };
    popupDialog.FindViewById<Button>(Resource.Id.dialog_cancel_button).Click += delegate { popupDialog.Dismiss(); };

    actionButton.Click += (sender, ev) => action.Action();
}

此外,使用这种方法可以很容易地添加新函数:只需派生一个新的 class 并覆盖 Action() 方法

您可以在ActionClassBase 中创建一个Dialog 并在Action() 中调用Dismiss() 方法。比如

abstract class ActionClassBase
{
  public  Dialog popupDialog;
  public abstract void Action();

  private string data = "";
  public string Data { get { return data; } set { data = value; } }
  }

class GetCurrentDateAction : ActionClassBase
{
  public override void Action()
  {
    Data = DateTime.Now.ToString();
    base.popupDialog.Dismiss();
  }
}

class OpenBlueToothAction : ActionClassBase
{
  public override void Action()
  {
    Data = "BlueTooth opened";
    base.popupDialog.Dismiss();
  }
}

然后,将对话框传递给 ShowDialogBox(Context context, Function dynamicFunction) 中的 ActionClassBase。如:

Dialog popupDialog = new Dialog(context);
popupDialog.SetContentView(Resource.Layout.dialog_dynamic);
popupDialog.Window.SetSoftInputMode(SoftInput.AdjustResize);
popupDialog.Window.SetBackgroundDrawableResource(Android.Resource.Color.Transparent);
dynamicFunction.popupDialog = popupDialog;