简单注入器 - 将 url 值注入服务构造函数
Simple Injector - Inject url value into service constructor
我不确定这是否可能,但可以。我正在使用 Simple Injector 并将我的服务接口注入到我的 api 控制器中。一切顺利。
我有 1 个可以使用不同 url 调用的控制器,例如可以使用这些 url 中的每一个来调用它
http://localhost/api/company
http://localhost/api/contact
http://localhost/api/cabbage
现在我需要知道最后一个词是什么,并在我的服务中使用它。
目前我有一个简单的界面,像这样
public interface IMyService() {
MyObject Get(long id);
}
然后是实现服务的基本服务
public class MyService : IMyService {
private IDbContext _context;
public MyService(IDbContext context) {
_context = context;
}
public MyObject Get(long id) {
// here i need that word!!
return _context.Database.RawQuery("SELECT * FROM something WHERE Id = " + id);
}
}
现在我的通用 api 控制器看起来像这样
[RoutePrefix("api/{myword}")]
public class MyController() {
private IMyService _service;
public MyController(IMyService service) {
_service = service;
}
public Get(long id) {
var model = Mapper.Map<ObjectModel>(_service.Get(id));
return Ok(model);
}
}
我想如果我能将那个词直接注入到我的服务中会更好。所以我必须将服务构造函数更改为这样
public MyService(IDbContext context, string theWord) {
_context = context;
// now I can store the word and use it in my service
}
我是 Simple Injector 的新手,所以不确定谁,或者即使您可以在每个 Web 请求的基础上注入那个词?所以每次创建控制器时,都会注入一个新服务,但这个词可能不同....
这可能吗,或者有人知道有更好的方法吗?
正如我所说,我正在使用 C#、ASP.NET WebApi 和简单注入器。
您可以在服务方法中看到请求 URL 并从那里计算出来:
public Get(long id)
{
var requestUri = Request.RequestUri.AbsoluteUri;
var theWord = requestUri.Substring(requestUri.LastIndexOf('/'));
var model = Mapper.Map<ObjectModel>(_service.Get(theWord, id));
return Ok(model);
}
你可以做类似
public class MyController() {
private IMyService _service;
public MyController(IMyService service) {
_service = service;
}
[Route("api/{serviceName}/{id}")] //url: api/myService/10
//restful [Route("api/service/{serviceName}/id/{id}")] //url: api/service/myService/id/10
public Get(string serviceName, long id) {
var model = Mapper.Map<ObjectModel>(_service.Get(id));
return Ok(model);
}
}
I am thinking it would be best if i could inject that word directly
into my service.
不,你绝对不应该这样做。这个 word
是一个运行时值(它是特定于请求的),你的对象图(你让 Simple Injector 建立的服务)不应该包含任何运行时数据。运行时数据应通过方法调用流动。
我认为@Trevor 的做法是正确的,尽管我不同意他的实现方式,因为您的业务层不应硬连接到您的表示框架。
相反,您应该将该词的检索置于抽象之后,我们称之为 IWordService
。这意味着 MyService
将如下所示:
public class MyService : IMyService {
private IDbContext _context;
private IWordService _wordService;
public MyService(IDbContext context, IWordService wordService) {
_context = context;
_wordService = wordService;
}
public MyObject Get(long id) {
string word = _wordService.CurrentWord;
// etc.
}
}
与IWordService
定义如下:
public interface IWordService {
string CurrentWord { get; }
}
这个接口显然应该位于你的业务层程序集中,或者你的业务层所依赖的程序集中。
并使用@Trevor 提供的代码,我们可以创建一个 ASP.NET 具体实现如下:
public sealed class AspNetWordService : IWordService {
public string CurrentWord {
get {
var requestUri = Request.RequestUri.AbsoluteUri;
var theWord = requestUri.Substring(requestUri.LastIndexOf('/'));
return theWord;
}
}
}
此 AspNetWordService
特定于 ASP.NET,显然应该放在您的 Web API 项目或其相关程序集之一中。这个class的注册很简单:
container.RegisterSingleton<IWordService>(new AspNetWordService());
也许,此 AspNetWordService
实施可能不会完全按照您的意愿进行,但更改它应该不难。更改此 class 不会影响系统的任何部分。
我不确定这是否可能,但可以。我正在使用 Simple Injector 并将我的服务接口注入到我的 api 控制器中。一切顺利。
我有 1 个可以使用不同 url 调用的控制器,例如可以使用这些 url 中的每一个来调用它
http://localhost/api/company
http://localhost/api/contact
http://localhost/api/cabbage
现在我需要知道最后一个词是什么,并在我的服务中使用它。
目前我有一个简单的界面,像这样
public interface IMyService() {
MyObject Get(long id);
}
然后是实现服务的基本服务
public class MyService : IMyService {
private IDbContext _context;
public MyService(IDbContext context) {
_context = context;
}
public MyObject Get(long id) {
// here i need that word!!
return _context.Database.RawQuery("SELECT * FROM something WHERE Id = " + id);
}
}
现在我的通用 api 控制器看起来像这样
[RoutePrefix("api/{myword}")]
public class MyController() {
private IMyService _service;
public MyController(IMyService service) {
_service = service;
}
public Get(long id) {
var model = Mapper.Map<ObjectModel>(_service.Get(id));
return Ok(model);
}
}
我想如果我能将那个词直接注入到我的服务中会更好。所以我必须将服务构造函数更改为这样
public MyService(IDbContext context, string theWord) {
_context = context;
// now I can store the word and use it in my service
}
我是 Simple Injector 的新手,所以不确定谁,或者即使您可以在每个 Web 请求的基础上注入那个词?所以每次创建控制器时,都会注入一个新服务,但这个词可能不同....
这可能吗,或者有人知道有更好的方法吗?
正如我所说,我正在使用 C#、ASP.NET WebApi 和简单注入器。
您可以在服务方法中看到请求 URL 并从那里计算出来:
public Get(long id)
{
var requestUri = Request.RequestUri.AbsoluteUri;
var theWord = requestUri.Substring(requestUri.LastIndexOf('/'));
var model = Mapper.Map<ObjectModel>(_service.Get(theWord, id));
return Ok(model);
}
你可以做类似
public class MyController() {
private IMyService _service;
public MyController(IMyService service) {
_service = service;
}
[Route("api/{serviceName}/{id}")] //url: api/myService/10
//restful [Route("api/service/{serviceName}/id/{id}")] //url: api/service/myService/id/10
public Get(string serviceName, long id) {
var model = Mapper.Map<ObjectModel>(_service.Get(id));
return Ok(model);
}
}
I am thinking it would be best if i could inject that word directly into my service.
不,你绝对不应该这样做。这个 word
是一个运行时值(它是特定于请求的),你的对象图(你让 Simple Injector 建立的服务)不应该包含任何运行时数据。运行时数据应通过方法调用流动。
我认为@Trevor 的做法是正确的,尽管我不同意他的实现方式,因为您的业务层不应硬连接到您的表示框架。
相反,您应该将该词的检索置于抽象之后,我们称之为 IWordService
。这意味着 MyService
将如下所示:
public class MyService : IMyService {
private IDbContext _context;
private IWordService _wordService;
public MyService(IDbContext context, IWordService wordService) {
_context = context;
_wordService = wordService;
}
public MyObject Get(long id) {
string word = _wordService.CurrentWord;
// etc.
}
}
与IWordService
定义如下:
public interface IWordService {
string CurrentWord { get; }
}
这个接口显然应该位于你的业务层程序集中,或者你的业务层所依赖的程序集中。
并使用@Trevor 提供的代码,我们可以创建一个 ASP.NET 具体实现如下:
public sealed class AspNetWordService : IWordService {
public string CurrentWord {
get {
var requestUri = Request.RequestUri.AbsoluteUri;
var theWord = requestUri.Substring(requestUri.LastIndexOf('/'));
return theWord;
}
}
}
此 AspNetWordService
特定于 ASP.NET,显然应该放在您的 Web API 项目或其相关程序集之一中。这个class的注册很简单:
container.RegisterSingleton<IWordService>(new AspNetWordService());
也许,此 AspNetWordService
实施可能不会完全按照您的意愿进行,但更改它应该不难。更改此 class 不会影响系统的任何部分。