我在Windows服务上自托管WebAPI,目标是能够与Windows服务进行通信。
然而,尽管我能够在基本级别上毫无困难地连接到我的Web服务,但我很清楚Web服务与它的主机之间的关系。如果我的最终目标是通过Web服务从Windows服务公开信息,我如何共享信息并在它们之间进行通信? Web服务代码可以访问Windows服务代码中的内容吗?
编辑:嗯,太广了......如何缩小范围?这是我的代码。我想要做的是调用“api / strings / 0”并让它返回“One”。但是,List indexOfStrings位于Windows服务主机中。 Web服务控制器如何访问信息?
public class StringsController : ApiController
{
/// <summary>
/// Get one entry from indexOfStrings
/// </summary>
public string Get(int listIndex)
{
// How to return indexOfStrings[listIndex]?
return "";
}
}
public class TestWindowsService : ServiceBase
{
public const string ServiceAddress = "Address and port number";
private HttpSelfHostServer _server; // This is the server you're hosting WebAPI on
private HttpSelfHostConfiguration _config; // WebAPI config
private List<string> indexOfStrings = new List<string>();
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
TestWindowsService service = new TestWindowsService() { AutoLog = false };
ServiceBase.Run(service);
}
public TestWindowsService()
{
indexOfStrings.Add("One");
indexOfStrings.Add("Two");
indexOfStrings.Add("Three");
//Create a host configuration
_config = new HttpSelfHostConfiguration(ServiceAddress);
//Setup the routes
_config.Routes.MapHttpRoute(
name: "DefaultGetApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional });
// Create the server
_server = new HttpSelfHostServer(_config);
}
protected override void OnStart(string[] args)
{
_server.OpenAsync();
}
protected override void OnStop()
{
_server.CloseAsync().Wait();
_server.Dispose();
}
}
答案 0 :(得分:2)
您可以通过插入依赖注入容器框架(如Unity,Ninject,Autofac,Structure Map等)并在容器中注册服务然后将该服务注入控制器来完成此操作。大多数DI框架都有Nuget包来支持Web API。
有一个使用Autofac here
的例子但是,使用相同的基本原则,您可以在不使用DI框架的情况下将服务级别对象公开给控制器方法。
我们的想法是使用MessageHandler将对象实例插入Request Properties集合,然后在控制器方法中将其拉回。
public class MyServiceHandler : DelegatingHandler
{
private readonly MyService _service;
public MyServiceHandler(MyService service)
{
_service = service;
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Properties["MyService_Key"] = _service;
return base.SendAsync(request, cancellationToken);
}
}
在配置代码中,您可以使用
将消息处理程序添加到管道 config.MessageHandlers.Add(new MyServiceHandler(new MyService()));
在您的控制器中,您可以访问此类服务
public class StringsController : ApiController
{
/// <summary>
/// Get one entry from indexOfStrings
/// </summary>
public string Get(int listIndex)
{
var myService = Request.Properties["MyService_Key"] as MyService;
// How to return indexOfStrings[listIndex]?
var mystring = myService.GetMyString(99);
return "";
}
}
理想情况下,您应该使用辅助方法或ApiController扩展方法来包装对服务的访问,但这些只是装饰性细节。
现在,您需要小心,因为现在可以在不同的线程上同时调用MyService。您需要确保使用并发集合来存储数据,或者在必要时使用锁。