Simple Injector - 将url值注入服务构造函数

时间:2015-05-15 14:56:14

标签: c# .net asp.net-web-api dependency-injection simple-injector

我不确定这是否可行,但这里有。我正在使用Simple Injector并将我的服务接口注入到我的apiControllers中。一切都很好。

我有一个可以使用不同网址调用的控制器,例如可以使用这些网址中的每个网址调用

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的新手,所以不确定是谁,或者即使你可以在每个网络请求的基础上注入这个词?因此,每次创建控制器时,都会注入一个新服务,但该字可能不同......

这可能吗,或者有人知道有更好的方法吗?

正如我所说,我使用的是C#,ASP.NET WebApi和Simple Injector。

3 个答案:

答案 0 :(得分:3)

  

我想我最好能直接注入这个词   进入我的服务。

不,你绝对不应该这样做。此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项目或其相关程序集中。这门课程的注册很简单:

container.RegisterSingleton<IWordService>(new AspNetWordService());

也许,这个AspNetWordService实现可能不会完全按照您的意愿执行,但它不应该很难改变它。更改此课程不会影响系统的任何部分。

答案 1 :(得分:1)

您可以执行类似

的操作
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);
    }    
}

答案 2 :(得分:0)

您可以在服务方法中查看请求网址并从中找出:

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);
}