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

能否在C# REST API控制器中访问非静态对象?附缓存复用需求

解决方案:通过ASP.NET Core依赖注入注册单例服务

你需要利用ASP.NET Core的依赖注入(DI)系统,将你的GenAPI对象注册为单例服务——这样它会在应用启动时创建一次,并且在整个应用生命周期内复用,完美符合你“不重复创建、自行维持存活并刷新数据”的需求。下面是具体实现步骤:

步骤1:将GenAPI注册为单例服务

在Startup类的ConfigureServices方法中,把GenAPI添加到服务容器,指定为单例生命周期:

public class Startup {
    public Startup(IConfiguration configuration) {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services) {
        // 注册GenAPI为单例:整个应用仅创建一个实例
        services.AddSingleton<GenAPI>(sp => {
            var genInstance = new GenAPI();
            // 如果需要初始化时执行额外逻辑(比如启动缓存刷新任务),可以在这里添加
            return genInstance;
        });

        services.AddMvc();
    }

    // ... 其他代码保持不变
}

如果你不需要额外初始化逻辑,也可以简化为:

services.AddSingleton<GenAPI>(new GenAPI());

步骤2:在ValuesController中通过构造函数注入GenAPI

修改控制器的构造函数,让DI容器自动注入单例的GenAPI实例,之后你就可以在Action中直接使用它了:

namespace GenAPI.Controllers {
    [Route("")]
    public class ValuesController : Controller {
        // 保存注入的GenAPI实例(用readonly确保不会被重新赋值)
        private readonly GenAPI _gen;

        // 构造函数注入:DI容器会自动传入单例的GenAPI对象
        public ValuesController(GenAPI gen) {
            _gen = gen;
        }

        [HttpGet("{url}")]
        public IEnumerable<string> Get(string url) {
            List<string> result = new List<string>();
            
            // 直接使用注入的_gen实例访问table数据
            foreach (var r in _gen.table.Rows) {
                result.Add(r[0].ToString()); // 注意转换为string,避免编译报错
            }
            
            return result;
        }

        // ... 其他Action(Post/Put/Delete)保持不变
    }
}

为什么这比全局变量更好?

  • 符合ASP.NET Core设计规范:依赖注入是框架的核心设计模式,便于维护和扩展。
  • 可测试性更强:单元测试时可以轻松mockGenAPI对象,而不用依赖真实的数据库或缓存。
  • 资源管理更安全:DI容器会自动处理单例对象的生命周期(比如实现IDisposable接口时,应用关闭时会自动调用Dispose释放资源)。

补充:让GenAPI自动刷新缓存

如果你的GenAPI需要定期刷新数据库数据,可以在类内部添加定时任务,比如用Timer实现:

public class GenAPI : IDisposable {
    public DataTable table { get; private set; }
    private Timer _refreshTimer;

    public GenAPI() {
        // 首次加载数据
        RefreshDatabaseData();
        // 设置每5分钟刷新一次(可根据需求调整间隔)
        _refreshTimer = new Timer(RefreshDatabaseData, null, TimeSpan.Zero, TimeSpan.FromMinutes(5));
    }

    private void RefreshDatabaseData(object state = null) {
        // 这里写查询数据库并更新table的逻辑
        // 示例:
        // using(var connection = new SqlConnection(Configuration.GetConnectionString("YourDb")))
        // {
        //     connection.Open();
        //     var command = new SqlCommand("SELECT * FROM YourTargetTable", connection);
        //     table = new DataTable();
        //     table.Load(command.ExecuteReader());
        // }
    }

    // 释放Timer资源,避免内存泄漏
    public void Dispose() {
        _refreshTimer?.Dispose();
    }
}

这样你的GenAPI就会自动维持数据刷新,完全不需要控制器干预。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:04:45