我如何指定的类实例我希望我的控制器的构造函数接收(通过Web API,DI工作时,和温莎城堡)? [英] How do I specify the class instance I want my Controller's constructor to receive (when working with Web API, DI, and Castle Windsor)?

本文介绍了我如何指定的类实例我希望我的控制器的构造函数接收(通过Web API,DI工作时,和温莎城堡)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

也许我的问题<一href=\"http://stackoverflow.com/questions/20846691/where-is-the-magic-happening-when-a-controller-instantiates-the-correct-implem\">here和<一个href=\"http://stackoverflow.com/questions/20843810/how-can-i-incorporate-this-castle-windsor-di-$c$c-into-my-controller-and-reposit\">here不够清晰,所以我会尽力减少
冗长而没有降低清晰度。

Perhaps my questions here and here are not clear enough, so I'll try to decrease the verbosity while not reducing the clarity.

说我控制器采用DI(你可以用语言表达为在你的脑袋 - 你不必大声说出它);所以它可能是这样的:

Say my Controller uses DI (you can verbalize it "in your head" - you don't have to utter it out loud); so it could look like this:

private readonly IDepartmentRepository _deptsRepository;

    public DepartmentsController(IDepartmentRepository deptsRepository)
    {
        if (deptsRepository == null)
        {
            throw new ArgumentNullException("deptsRepository is null");
        }
        _deptsRepository = deptsRepository;
    }

这样的话,我可以拦截网页API路由机制,有它传递实现IDepartmentRepository到控制器的构造特定类。所以,如果我的接口是:

That way, I can intercept the Web API routing mechanism, having it pass a particular class that implements IDepartmentRepository to the Controller's constructor. So, if my interface is:

public interface IDepartmentRepository
{
    int Get();
    IEnumerable<Department> Get(int ID, int CountToFetch);
    Department Add(Department item);
    void Post(Department dept);
    void PostDepartment(int accountid, string name);
    void Put(Department dept);
    void Delete(int Id);
}

...我可以上课是这样的:

...I could have classes like this:

public class DepartmentRepositoryProductionData : IDepartmentRepository
{
    private readonly List<Department> departments = new List<Department>();

    public DepartmentRepository()
    {
        using (var conn = new OleDbConnection(
            @"Provider=Microsoft.ACE.OLEDB.12.0;User ID=BlaBlaBla..."))
        {
...                        

...这:

public class DepartmentRepositoryTestData : IDepartmentRepository
{
    private readonly List<Department> departments = new List<Department>();

    public DepartmentRepository()
    {
        // Load test data from an XML file (or text file, or whatever)
...                        

现在,这只是花花公子,但如何/我在哪里指定我想成为一个控制器实例DepartmentRepositoryTestData(或DepartmentRepositoryProductionData)的实例?我衷心地拥抱延迟类,直到运行时的识别的概念,但即使阅读了不少关于DI后,我失去了如何以及其中一个指定哪一个类(即实现了所需的接口)控制器将接收部分在其构造ARG。

Now, that's just dandy, but how/where do I specify that I want an instance of DepartmentRepositoryTestData (or DepartmentRepositoryProductionData) to be the one the Controller instantiates? I heartily embrace the concept of delaying the identification of the class until runtime, but even after reading quite a bit about DI, I'm missing the part about how and where one specifies which class (that implements the required interface) the Controller will receive in its constructor arg.

时它由客户,由IOW什么的URI通过指定?我想不会,但我有点困惑所以一切皆有可能。

Is it specified by the Client, IOW by what's passed in the URI? I would think not, but I am a bit baffled so "anything is possible."

由于这显然是不够明确的是,我要补充一点:

Since this is apparently not clear enough yet, I'll add this:

有关这个抽象(ARG接口为控制器构造函数)是任何值,不过,必须有实现接口的多个类,对吧?这可能是一个测试数据类和生产数据类,或者它可能是一个加州比萨类和纽约的比萨级,或加利福尼亚,纽约,芝加哥和意大利类,都实现IPizzaPie。

For this abstraction (interface arg for the Controller constructor) to be of any value, though, there has to be multiple classes that implement that interface, right? This could be a "test data" class and a "production data" class, or it could be a "California Pizza" class and a "New York Pizza" class, or California, New York, Chicago, and Italy classes that all implement IPizzaPie.

但有人的地方必须是交通警察,上面写着:实例化类加州或实例化纽约班等。

But somebody somewhere has to be the traffic cop that says: "Instantiate the California class" or "Instantiate the New York class" etc.

这是我的问题:谁/这是哪里交通警察(类实例决胜局),以及我们告诉它如何通过其类

That's my question: who/where is this traffic cop (class instance decider), and how do we tell it which class to pass?

这似乎可能在这里被指定的类类型的地方是,当此构造(在我的WindsorCompositionRoot.cs),被称为:

It would seem that possibly the place where the class type is being specified is when this constructor (in my "WindsorCompositionRoot.cs") is called:

public IHttpController Create(
    HttpRequestMessage request,
    HttpControllerDescriptor controllerDescriptor,
    Type controllerType)
{
    var controller =
        (IHttpController)this.container.Resolve(controllerType);

    request.RegisterForDispose(
        new Release(
            () => this.container.Release(controller)));

    return controller;
}

...但我仍然不知道谁调用这个(IHttpController)...

...but I still don't know who calls this (IHttpController)...

帮助,也是如此

推荐答案

在一般情况下,如果你正在做某种形式的TDD,并想写孤立的测试,我会推荐的针对连线了集装箱做你的测试。你会想消除容器从设备完全测试。

In general, if you are doing some form of TDD, and wanted to write isolated tests, I would recommend against wiring up a container to do your testing. You would want to eliminate the container from your unit tests completely.

所以,如果你想测试控制器,你会做这样的事情:

So if you wanted to test the controller, you would do something like:

var sut = new DepartmentsController(new DepartmentRepositoryTestData());

此假设你想有IDepartmentRepository一个具体的测试类代替使用某种嘲讽的框架中。

This assumes you do want to have a concrete test class for IDepartmentRepository in lieu of using some sort of mocking framework.

如果这更是一个集成测试,而你想线了一个容器来测试类之间的互动,那么这将是你的容器的注册code的责任。你应该有单独的容器注册,测试与故事生产的故事,这样的服务将解析为根据上下文不同的具体实例。

If this is more of an integration test, and you DO want to wire up a container to test interaction between classes, then this would be the responsibility of your container registration code. You should have separate container registration for a testing story vs. a production story, so that services would resolve to different concrete instances based on context.

修改

我想你实际上是在问这里的两个问题:一是有关路由和参数,以及其他有关的DI。我打算从DI的角度来回答。

I think you are actually asking two questions here: one about routing and parameters, and the other about DI. I'm going to answer from the perspective of DI.

您说这样的:

有关这种抽象(用于控制器构造接口ARG)至
  为任意值,不过,必须有多个类,
  实现该接口,对吧?

For this abstraction (interface arg for the Controller constructor) to be of any value, though, there has to be multiple classes that implement that interface, right?

您是说,如果有一个以上的实施一个接口/抽象是唯一有用吗?我觉得这是见仁见智的问题,但谁使用DI创建界面许多人,以促进松散耦合,即使只有一个(生产)执行。通常情况下,第二次或以后的实施是一个模拟。

You are saying an interface/abstraction is only useful if there is more than one implementation? I think this is a matter of opinion, but many people who use DI create interfaces to promote loose coupling, even if there is only one (production) implementation. Often the second or subsequent implementation is a mock.

这可能是一个测试数据类和生产数据级,或者
  可能是加州比萨类和纽约的比萨级,或
  加利福尼亚,纽约,芝加哥和意大利类,都实现
  IPizzaPie。

This could be a "test data" class and a "production data" class, or it could be a "California Pizza" class and a "New York Pizza" class, or California, New York, Chicago, and Italy classes that all implement IPizzaPie.

但有人的地方必须是交通警察,上面写着:
  实例化类加州或实例化纽约班
  等等。

But somebody somewhere has to be the traffic cop that says: "Instantiate the California class" or "Instantiate the New York class" etc.

这是我的问题:谁/这是哪里交通警察(类实例
  决胜局),以及我们如何告诉它传递哪些类?

That's my question: who/where is this traffic cop (class instance decider), and how do we tell it which class to pass?

我认为你正在寻找在这里所谓的抽象工厂。你可以注册一个接口的多个实例,然后创建一个工厂,会根据一些标准的FPGA实现。

I think what you are looking for here is called an Abstract Factory. You can register multiple instances of an interface, and then create a factory that chooses the implemention based on some criteria.

关于这个问题的好文章:
http://blog.ploeh.dk/2012/03/15/ImplementinganAbstractFactory/

Good article on the subject: http://blog.ploeh.dk/2012/03/15/ImplementinganAbstractFactory/

编辑#2

在您最后一次更新发布的code是负责解决的ASP.Net MVC正确的控制器。这简直是​​必需的水暖MVC使用DI工作。

The code you posted in your last update is responsible for resolving the right controller for ASP.Net MVC. This is simply required plumbing for MVC to work using DI.

您正在试图返回基于某种语境的具体实施服务。这一般是用抽象工厂完成,如我如上所述。您可以创建一个工厂接口,并将其注入到通过构造控制器,然后在控制器方法或构造函数调用它是这样的:

You are trying to return a specific implementation of a service based on some sort of context. This is generally done with an abstract factory, as I noted above. You would create a factory interface and inject it into the controller via the constructor, and then call it like this in a controller method or constructor:

IDepartmentRepository回购= _departmentRepoFactory.Create(myContext);

IDepartmentRepository repo = _departmentRepoFactory.Create(myContext);

你看它的任何方式,一些code某处有权要求集装箱供应的基础上实现的的东西的(一个字符串,枚举,整型等),以及这就是抽象工厂的用武之地。

Any way you look at it, some code somewhere has to request that the container supply an implementation based on something (a string, an enum, an integer, etc.), and this is where the abstract factory comes in.

这篇关于我如何指定的类实例我希望我的控制器的构造函数接收(通过Web API,DI工作时,和温莎城堡)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆