能否在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设计规范:依赖注入是框架的核心设计模式,便于维护和扩展。
- 可测试性更强:单元测试时可以轻松mock
GenAPI对象,而不用依赖真实的数据库或缓存。 - 资源管理更安全: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
相关产品推荐
相关产品推荐

