You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor组件为何可传Void方法却无法传递Action?

问题描述

我开发了一个基于MudBlazor的Blazor对话框组件SimpleDialogComponent,组件代码如下:

<MudDialog>
<DialogContent>
    <MudText>@ContentText</MudText>
</DialogContent>
<DialogActions>
    <MudButton OnClick="Cancel">@CancelButtonText</MudButton>
    <MudButton Color="@Color" Variant="Variant.Filled" OnClick="@InvokeOkAction">@ButtonText</MudButton>
</DialogActions>
</MudDialog>

@code {
    [CascadingParameter] MudDialogInstance? MudDialog { get; set; }
    [Parameter] public string? ContentText { get; set; }
    [Parameter] public string? ButtonText { get; set; }
    [Parameter] public string? CancelButtonText { get; set; } = "Anuluj";
    [Parameter] public Color Color { get; set; }

    [Parameter] public Action? OkAction { get; set; }

    private void InvokeOkAction()
    {
        OkAction?.Invoke();
        MudDialog?.Close(DialogResult.Ok(true));
    }

    void Cancel() => MudDialog?.Cancel();
}

调用该组件的代码如下:

private void SaveAsProd()
{
    var parameters = new DialogParameters();
    parameters.Add("ContentText", "Do you really want to delete these records?");
    parameters.Add("ButtonText", "Delete");
    parameters.Add("OkAction", okaction!);
    var options = new DialogOptions() { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall };

    DialogService.Show<SimpleDialogComponent>("????", parameters, options);
}

private void okaction() { Console.WriteLine("asd");}

private Action okaction2(){ return ()=> Console.WriteLine("asd");}

传递无返回值的okaction方法时可正常运行,但传递okaction2返回的Action对象或Lambda表达式时,抛出如下异常:

Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
  Unhandled exception rendering component: Unable to set property 'OkAction' on object of type 'xx.Client.Components.SimpleDialogComponent'. The error was: Specified cast is not valid.
 System.InvalidOperationException: Unable to set property 'OkAction' on object of type 'xx.Client.Components.SimpleDialogComponent'. The error was: Specified cast is not valid.
 ---&gt; System.InvalidCastException: Specified cast is not valid.

请问这是什么原因?为何无法传递Action?使用Lambda表达式也会出现相同错误。

原因与解决方法

核心原因

MudBlazor的DialogParameters在处理委托类型参数时,对直接的方法组(如okaction)兼容性较好,但当传递匿名委托(Lambda)或动态生成的Action实例时,编译器会生成特定的匿名委托类型,而非直接的System.Action,导致类型转换失败。另外Blazor组件参数绑定系统对这类动态委托的解析支持有限。

解决方法

方法1:改用Func<Task>替代Action

将组件中的同步委托改为异步委托类型,适配Blazor的参数传递机制:

@code {
    // 替换原有Action参数
    [Parameter] public Func<Task>? OkAction { get; set; }

    private async Task InvokeOkAction()
    {
        if (OkAction != null)
        {
            await OkAction();
        }
        MudDialog?.Close(DialogResult.Ok(true));
    }
}

调用时,所有形式的委托都能正常传递:

// 传递Lambda
parameters.Add("OkAction", () => 
{
    Console.WriteLine("asd");
    return Task.CompletedTask;
});

// 传递okaction2返回的委托
parameters.Add("OkAction", okaction2());

// 原方法组调整为异步
private async Task okaction() { Console.WriteLine("asd");}
private Func<Task> okaction2(){ return ()=> 
{
    Console.WriteLine("asd");
    return Task.CompletedTask;
};}

方法2:通过DialogResult触发回调

绕过组件参数传递委托,改为在对话框关闭后统一处理回调逻辑:

private async void SaveAsProd()
{
    var parameters = new DialogParameters();
    parameters.Add("ContentText", "Do you really want to delete these records?");
    parameters.Add("ButtonText", "Delete");
    var options = new DialogOptions() { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall };

    var dialog = DialogService.Show<SimpleDialogComponent>("Confirm", parameters, options);
    var result = await dialog.Result;

    if (!result.Canceled)
    {
        // 执行原OkAction逻辑
        Console.WriteLine("asd");
        // 或调用动态生成的委托
        okaction2().Invoke();
    }
}

此时组件可移除OkAction参数,仅保留对话框关闭逻辑即可。

内容的提问来源于stack exchange,提问作者Dorian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 08:52:49