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

C#异步场景下属性与方法选型及强制重载方案咨询

适配延迟加载+强制重载场景的实现方案

问题核心

需要实现类中多个属性的异步延迟加载,同时支持强制重载(刷新),还要避免同步阻塞和方法膨胀的问题。

优化方案:封装可刷新的异步延迟加载容器

自己封装通用的AsyncRefreshableLazy<T>类,把延迟加载、异步处理、强制刷新的逻辑抽离,避免每个属性重复写判断代码,也不用给每个属性加单独的GetXXXAsync方法。

通用容器实现

public class AsyncRefreshableLazy<T> where T : class
{
    private readonly Func<Task<T>> _factory;
    private Task<T>? _cachedTask;

    public AsyncRefreshableLazy(Func<Task<T>> factory)
    {
        _factory = factory ?? throw new ArgumentNullException(nameof(factory));
    }

    public async Task<T> GetValueAsync(bool forceRefresh = false)
    {
        if (forceRefresh || _cachedTask == null)
        {
            _cachedTask = _factory();
        }
        return await _cachedTask.ConfigureAwait(false);
    }

    // 可选:同步获取(仅兼容旧代码,不推荐)
    public T GetValue(bool forceRefresh = false)
    {
        return GetValueAsync(forceRefresh).GetAwaiter().GetResult();
    }
}

在业务类中的使用

public class YourBusinessClass
{
    private readonly AsyncRefreshableLazy<EntArchElement> _classifier;
    private readonly AsyncRefreshableLazy<AnotherSubType> _anotherProperty;
    // 其他子类型属性...

    public YourBusinessClass(IRepository repository, Guid classifierGuid, Guid anotherGuid)
    {
        _classifier = new AsyncRefreshableLazy<EntArchElement>(
            () => repository.GetElementAsync(classifierGuid));
        
        _anotherProperty = new AsyncRefreshableLazy<AnotherSubType>(
            () => repository.GetAnotherElementAsync(anotherGuid));
        // 初始化其他属性...
    }

    // 对外暴露异步属性(C# 8.0+支持)
    public Task<EntArchElement> Classifier => _classifier.GetValueAsync();
    
    // 带强制重载参数的方法,统一调用风格
    public Task<EntArchElement> GetClassifierAsync(bool forceRefresh = false)
    {
        return _classifier.GetValueAsync(forceRefresh);
    }

    // 其他属性同理
    public Task<AnotherSubType> AnotherProperty => _anotherProperty.GetValueAsync();
    public Task<AnotherSubType> GetAnotherPropertyAsync(bool forceRefresh = false)
    {
        return _anotherProperty.GetValueAsync(forceRefresh);
    }
}

方案优势

  • 代码复用:所有延迟加载+刷新逻辑都在通用容器中,业务类无需重复编写判断代码
  • 异步友好:全程异步操作,避免.Result阻塞线程
  • 灵活调用:既可以用异步属性简化常规获取,也可以用带forceRefresh参数的方法触发重载
  • 线程安全扩展:如果需要多线程场景,可给_cachedTask的赋值加锁或用Interlocked.Exchange保证原子性,示例如下:

线程安全版容器扩展

public async Task<T> GetValueAsync(bool forceRefresh = false)
{
    if (!forceRefresh && _cachedTask != null)
    {
        return await _cachedTask.ConfigureAwait(false);
    }

    var newTask = _factory();
    var oldTask = Interlocked.Exchange(ref _cachedTask, newTask);
    // 非强制刷新时,优先用旧任务避免并发重复加载
    if (!forceRefresh && oldTask != null)
    {
        return await oldTask.ConfigureAwait(false);
    }

    return await newTask.ConfigureAwait(false);
}

替代思路:属性包装器(C# 9.0+)

如果使用C# 9.0及以上版本,可尝试用属性包装器进一步简化,但目前C#原生不支持自定义属性包装器,需借助Source Generator或第三方库实现,相比之下通用容器方案更通用且无额外依赖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 16:48:24