9

更新:有没有办法在 Windsor 以外的 IoC 框架中实现我想要做的事情?Windsor 会很好地处理控制器,但不会解决其他任何问题。我确定这是我的错,但我正在逐字遵循教程,并且对象没有通过 ctor 注入解析,尽管进行了注册和解析,它们仍然为空。我已经废弃了我的 DI 代码并暂时进行手动注入,因为该项目对时间很敏感。希望在截止日期前完成 DI。


我有一个解决方案,它有多个类都实现了相同的接口

举个简单的例子,Interface

public interface IMyInterface {
    string GetString();
    int GetInt();
   ...
}

具体类

public class MyClassOne : IMyInterface {
    public string GetString() {
        ....
    }
    public int GetInt() {
        ....
    }
}

public class MyClassTwo : IMyInterface {
    public string GetString() {
        ....
    }
    public int GetInt() {
        ....
    }
}

现在这些类将在需要的地方注入到它们上面的层中,例如:

public class HomeController {

    private readonly IMyInterface myInterface;

    public HomeController() {}

    public HomeController(IMyInterface _myInterface) {
        myInterface = _myInterface
    }
    ...
}

public class OtherController {

    private readonly IMyInterface myInterface;

    public OtherController() {}

    public OtherController(IMyInterface _myInterface) {
        myInterface = _myInterface
    }
    ...
}

两个控制器都注入了相同的接口。

在我的 IoC 中使用适当的具体类解决这些接口时,我如何区分HomeController需要一个实例MyClassOneOtherController需要一个实例MyClassTwo

如何将两个不同的具体类绑定到 IoC 中的同一个接口?我不想创建 2 个不同的接口,因为这违反了 DRY 规则并且无论如何都没有意义。

在温莎城堡中,我会有 2 行这样的:

container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassOne>());
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassTwo>());

这行不通,因为我只会得到一个副本,MyClassTwo因为它是为接口注册的最后一个。

就像我说的,如果不为每个具体实例创建特定的接口,我不知道如何做到这一点,这样做不仅违反了 DRY 规则,而且也违反了基本的 OOP。我如何实现这一目标?


根据 Mark Polsen 的回答进行更新


这是我目前的 IoC,.Resolve声明会去哪里?我在 Windsor 文档中看不到任何内容

public class Dependency : IDependency {

    private readonly WindsorContainer container = new WindsorContainer();

    private IDependency() {
    }

    public IDependency AddWeb() {
        ...

        container.Register(Component.For<IListItemRepository>().ImplementedBy<ProgramTypeRepository>().Named("ProgramTypeList"));
        container.Register(Component.For<IListItemRepository>().ImplementedBy<IndexTypeRepository>().Named("IndexTypeList"));

        return this;
    }

    public static IDependency Start() {
        return new IDependency();
    }
}
4

3 回答 3

7

我希望您可以使用服务覆盖

前任。

container.Register(
    Component.For<IMyService>()
        .ImplementedBy<MyServiceImpl>()
        .Named("myservice.default"),
    Component.For<IMyService>()
        .ImplementedBy<OtherServiceImpl>()
        .Named("myservice.alternative"),

    Component.For<ProductController>()
        .ServiceOverrides(ServiceOverride.ForKey("myService").Eq("myservice.alternative"))
);

public class ProductController
{
    // Will get a OtherServiceImpl for myService.
    // MyServiceImpl would be given without the service override.
    public ProductController(IMyService myService)
    {
    }
}
于 2012-06-11T16:00:49.710 回答
5

您应该能够通过命名组件注册来完成它。

container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassOne>().Named("One"));
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassTwo>().Named("Two"));

然后解决它们

kernel.Resolve<IMyInterface>("One");

或者

kernel.Resolve<IMyInterface>("Two");

请参阅:指定组件的名称

于 2012-06-11T16:01:38.000 回答
2

通常 DI 容器遵循 Register、Resolve 和 Release 模式。在注册阶段有两个步骤。第一个是按照您的操作指定映射。第二步是指定规则,这些规则控制在哪里注入。

当我们尝试使用装饰器解决横切关注点时,这个问题很常见。在这些情况下,您有多个类(装饰器)实现一个接口。

简而言之,我们需要实现 IModelInterceptorsSelector,它允许您编写命令式代码来决定将哪个 Interceptor 应用于哪些类型或成员。

这在 Mark Seemann 所著的 .Net 中的 Dependency Injection 一书中进行了详细描述。寻找第9章拦截或搜索上述接口。

我不是这方面的专家,但正在寻找完全相同的问题并在上面的书中找到了答案。

希望这可以帮助。

问候 Dev1

于 2013-06-23T09:06:59.073 回答