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

如何将Razor组件中重复的通用函数封装为可注入服务?

当然可以!甚至这是解决这类重复代码问题的最佳实践之一

你提到的思路和仓储模式的核心逻辑一致——把通用、重复的逻辑抽离到独立的服务类中,通过依赖注入让需要的Razor组件使用,既能大幅减少代码重复,也方便后续统一维护。

针对你的TrySelect函数,这里分两种场景给出具体实现方案:

场景1:组件状态变量完全一致(所有26个组件都有_isOpen、SelectedText等变量)

这种情况可以用组件基类+服务的组合,彻底消除重复代码:

1. 封装通用逻辑到服务(处理与组件无关的部分)

假设objSearchHotel是全局共享的对象,先把这部分逻辑封装成服务:

// 定义搜索酒店服务的接口(方便后续扩展和测试)
public interface ISearchHotelService
{
    object SearchObject { get; set; }
}

public class SearchHotelService : ISearchHotelService
{
    public object SearchObject { get; set; }
}

// 定义选择逻辑服务
public interface ISelectionService
{
    void SetCitySearchObject(clsCity item);
}

public class SelectionService : ISelectionService
{
    private readonly ISearchHotelService _searchHotelService;

    // 构造函数注入依赖
    public SelectionService(ISearchHotelService searchHotelService)
    {
        _searchHotelService = searchHotelService;
    }

    public void SetCitySearchObject(clsCity item)
    {
        // 这部分是所有组件通用的逻辑
        _searchHotelService.SearchObject = item;
    }
}

2. 创建组件基类(处理组件状态相关的通用逻辑)

把所有组件共有的状态变量和TrySelect方法放到基类中:

public class BaseCitySelectorComponent : ComponentBase
{
    // 依赖注入选择服务
    [Inject] protected ISelectionService SelectionService { get; set; }

    // 所有组件共有的状态变量
    protected bool _isOpen;
    protected string SelectedText { get; set; }
    protected int SelectedValue { get; set; } // 可根据实际ID类型调整

    // 通用的选择方法
    protected void TrySelect(clsCity item)
    {
        _isOpen = false;
        SelectedText = item.Nombre;
        SelectedValue = item.ID;
        SelectionService.SetCitySearchObject(item);
        StateHasChanged();
    }
}

3. 组件继承基类并使用

所有需要TrySelect功能的组件直接继承基类即可:

public partial class ParisCitySelector : BaseCitySelectorComponent
{
    // 组件特有的UI或逻辑写在这里,无需重复写TrySelect
}

场景2:组件状态变量不一致(部分组件的状态变量名或逻辑有差异)

这种情况可以只把完全通用的逻辑封装到服务,组件自己处理状态更新:

1. 注册服务到依赖注入容器

在Program.cs中添加服务注册:

builder.Services.AddScoped<ISelectionService, SelectionService>();
builder.Services.AddScoped<ISearchHotelService, SearchHotelService>();

2. 组件中注入服务并简化方法

每个组件注入服务后,只需要维护自己的状态,通用逻辑交给服务处理:

private readonly ISelectionService _selectionService;

// 构造函数注入服务
public YourCustomCitySelector(ISelectionService selectionService)
{
    _selectionService = selectionService;
}

// 组件自己的状态变量(可能和其他组件名不同)
private bool _dropdownOpen;
private string _selectedCityName;
private Guid _selectedCityId; // 可根据实际ID类型调整

void TrySelect(clsCity item)
{
    // 组件特有的状态更新
    _dropdownOpen = false;
    _selectedCityName = item.Nombre;
    _selectedCityId = item.ID;
    
    // 调用通用服务逻辑
    _selectionService.SetCitySearchObject(item);
    
    StateHasChanged();
}

为什么这么做?

  • 减少重复代码:不用在26个文件中复制粘贴相同的函数,后续修改逻辑只需要改一处
  • 单一职责:组件专注于UI渲染和用户交互,服务专注于处理通用业务逻辑
  • 可测试性:服务类可以单独写单元测试,无需依赖组件
  • 灵活性:后续需要扩展逻辑(比如新增日志、校验),只需要修改服务即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 19:55:13