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

如何在自托管Web API与Windows服务间实现对象共享?

问题描述

我已创建一个简单的自托管Web API,以及一个本质为Windows服务的服务器。服务代码如下:

protected override void OnStart(string[] args)
{
    var config = new HttpSelfHostConfiguration("http://localhost:8085");

    config.Routes.MapHttpRoute(
       name: "API",
       routeTemplate: "{controller}/{action}/{id}",
       defaults: new { id = RouteParameter.Optional }
   );

    HttpSelfHostServer server = new HttpSelfHostServer(config);
    server.OpenAsync().Wait();
}

Web API代码如下:

public class ValuesController : ApiController
{
    public String GetString(Int32 id)
    {
        return "Test data";
    }
}

请问是否可以在该服务与Web API之间实现对象共享?例如在服务中连接数据库服务器,在Web API中使用该连接对象等。我对此毫无思路,在网上搜索也未找到合适的解决方案。

解决方案

当然可以实现服务与Web API之间的对象共享,以下是几种可行方案:

1. 使用ASP.NET Web API依赖注入(推荐)

这是最规范的实现方式,通过Web API的依赖解析器注册和共享对象:

  • 在Windows服务的OnStart方法中初始化需要共享的对象(如数据库连接工厂、EF DbContext等)
  • 配置Web API的依赖解析器,将对象注册为单例或对应生命周期的实例
  • 在API控制器中通过构造函数注入获取对象

示例修改代码:

// 服务OnStart方法中注册依赖
protected override void OnStart(string[] args)
{
    var config = new HttpSelfHostConfiguration("http://localhost:8085");

    // 初始化共享的数据库连接工厂
    var dbConnectionFactory = new DbConnectionFactory("your_connection_string");
    // 配置自定义依赖解析器
    config.DependencyResolver = new SimpleDependencyResolver(dbConnectionFactory);

    config.Routes.MapHttpRoute(
       name: "API",
       routeTemplate: "{controller}/{action}/{id}",
       defaults: new { id = RouteParameter.Optional }
   );

    HttpSelfHostServer server = new HttpSelfHostServer(config);
    server.OpenAsync().Wait();
}

// 自定义简单依赖解析器
public class SimpleDependencyResolver : IDependencyResolver
{
    private readonly object _sharedInstance;

    public SimpleDependencyResolver(object sharedInstance)
    {
        _sharedInstance = sharedInstance;
    }

    public object GetService(Type serviceType)
    {
        if (serviceType == typeof(DbConnectionFactory))
            return _sharedInstance;
        return null;
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return Enumerable.Empty<object>();
    }

    public IDependencyScope BeginScope()
    {
        return this;
    }

    public void Dispose()
    {
        // 按需释放资源
    }
}

// 修改控制器通过构造函数注入获取对象
public class ValuesController : ApiController
{
    private readonly DbConnectionFactory _dbFactory;

    public ValuesController(DbConnectionFactory dbFactory)
    {
        _dbFactory = dbFactory;
    }

    public String GetString(Int32 id)
    {
        // 使用连接工厂创建数据库连接
        using(var conn = _dbFactory.CreateConnection())
        {
            // 执行数据库操作
            return "Test data from DB";
        }
    }
}

2. 使用静态类存储共享对象

如果场景简单,可通过静态类存放共享对象,但必须注意线程安全:

// 静态共享资源类
public static class SharedResources
{
    public static DbConnectionFactory DbFactory { get; set; }
    // 可变状态需加锁保证线程安全
    private static readonly object _lockObj = new object();
}

// 服务OnStart中初始化
protected override void OnStart(string[] args)
{
    lock(SharedResources._lockObj)
    {
        SharedResources.DbFactory = new DbConnectionFactory("your_connection_string");
    }

    var config = new HttpSelfHostConfiguration("http://localhost:8085");
    // 路由配置...
    HttpSelfHostServer server = new HttpSelfHostServer(config);
    server.OpenAsync().Wait();
}

// 控制器中使用
public class ValuesController : ApiController
{
    public String GetString(Int32 id)
    {
        using(var conn = SharedResources.DbFactory.CreateConnection())
        {
            // 执行数据库操作
            return "Test data";
        }
    }
}

注意:不推荐直接共享数据库连接对象,数据库连接应随用随建、用完即释放(通过using语句),共享连接工厂或DbContext更合理,可利用ADO.NET连接池管理连接。

3. 服务定位器模式

通过全局服务容器获取共享对象,属于依赖注入的变体,适合快速改造现有代码:

// 全局服务容器
public static class ServiceLocator
{
    private static readonly Dictionary<Type, object> _services = new Dictionary<Type, object>();
    private static readonly object _lockObj = new object();

    public static void Register<T>(T instance)
    {
        lock(_lockObj)
        {
            _services[typeof(T)] = instance;
        }
    }

    public static T Get<T>()
    {
        lock(_lockObj)
        {
            if(_services.TryGetValue(typeof(T), out var instance))
                return (T)instance;
            throw new InvalidOperationException($"未注册类型为{typeof(T)}的服务");
        }
    }
}

// 服务OnStart中注册对象
protected override void OnStart(string[] args)
{
    ServiceLocator.Register(new DbConnectionFactory("your_connection_string"));
    // 其他配置...
}

// 控制器中获取对象
public class ValuesController : ApiController
{
    public String GetString(Int32 id)
    {
        var dbFactory = ServiceLocator.Get<DbConnectionFactory>();
        using(var conn = dbFactory.CreateConnection())
        {
            // 执行数据库操作
            return "Test data";
        }
    }
}

关键注意事项

  • 避免直接共享数据库连接:数据库连接是有状态资源,应由连接池管理,推荐共享连接工厂或DbContext
  • 保证线程安全:若共享对象是可变状态,必须通过锁或线程安全结构确保多线程环境下的稳定性
  • 合理管理生命周期:根据对象特性选择单例、作用域等生命周期,避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 06:47:43