c# - 在 Ninject 中寻找通用接口(interface)的具体实现

标签 c# generics dependency-injection ninject inversion-of-control

我有一个通用接口(interface),具体实现如下:

public class Animal { }
public class Horse : Animal { }
public class Dog : Animal { }

public interface Vet<in T> where T : Animal
{
    void Heal(T animal);
}

public class HorseVet : Vet<Horse>
{
    public void Heal(Horse animal)
    {
        Console.WriteLine("Healing a horse");
    }
}

public class DogVet : Vet<Dog>
{
    public void Heal(Dog animal)
    {
        Console.WriteLine("Healing a dog");
    }
}

现在我希望能够为 Vet<T> 的适当具体实现创建一个实例给出 Animal在运行时,如下所示:

StandardKernel kernel = new StandardKernel();
kernel.Bind<Vet<Horse>>().To<HorseVet>();
kernel.Bind<Vet<Dog>>().To<DogVet>();

var animals = new Animal[] { new Horse(), new Dog() };

foreach (Animal animal in animals)
{
    // how do I get the right Vet<T> type here so I can call Heal(animal)?
}

我的问题是,我怎样才能实现上述目标以便检索正确的实现,或者我是否需要重构为组织类的不同方式?

我看过 Ninject Factory Extension,但它似乎也没有提供我正在寻找的东西。

如果我不使用 IoC 容器,我会做类似的事情:

public Vet<Animal> Create(Animal animal)
{
    if (animal is Horse)
    {
        return new HorseVet();
    }
    else if ...
}

最佳答案

foreach (Animal animal in animals)
{
    Type vetType = typeof(Vet<>).MakeGenericType(animal.GetType());
    object vet = kernel.Get(vetType);
}

但是现在的问题就变成了你要怎么使用这个类型呢?您可能会想做这样的事情:

var vet = (Vet<Animal>)kernel.Get(vetType);
vet.Heal(animal);

但这不起作用,因为 Vet<Dog> 的实例和 Vet<Horse>无法转换为 Vet<Animal> ,因为这需要 Vet<T>out 定义关键字如 Vet<out Animal> .但这当然行不通,因为Vet<T>有一个类型为 Animal 的输入参数.

所以要解决这个问题,您要么需要第二个非泛型 Vet界面,或者您需要使用反射或动态类型。使用非通用接口(interface)可能如下所示:

public interface Vet {
    void Heal(Animal animal);
}

public interface Vet<T> : Vet where T : Animal {
    void Heal(T animal);
}

// Usage
var vet = (Vet)kernel.Get(vetType);
vet.Heal(animal);

然而,问题是这会污染实现,因为他们突然需要实现第二种方法。

另一种选择是使用动态类型或反射:

dynamic vet = kernel.Get(vetType);
vet.Heal((dynamic)animal);

缺点当然是你会失去编译时支持,但如果这两行代码是应用程序中唯一像这样调用 vet 的行,我会说它很好。您可以轻松添加检查此代码的单元测试。

顺便说一下,请注意 in Vet<in T> 上的关键字可能没用,除非你在 Dog 上都有 vert 实现和 GoldenRetriever并希望能够申请 GoldenRetrieverVet<Dog> .

关于c# - 在 Ninject 中寻找通用接口(interface)的具体实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33916021/

相关文章:

java - 在类本身中初始化泛型类型字段

sql-server - Node js - 导入 mssql 模块以用于 Angular 2 项目错误 : "Can' t resolve 'dns' "and " Can't resolve 'dgram' "

c# - 无法将字符串转换为 system.Net.HttpContent

c# - 在 SQL 查询或 UI 代码中计算金额(数量 * 价格)

C# 将 XML 数据存入字典

java - 当我在 Java 中迭代非泛型映射时,编译器会报错

c# - 将 Json 字符串转换为对象列表

java - 使用抽象类的ArrayList

spring - MapStruct 映射器未在 Spring 单元测试中注入(inject)

scala - 比较Subcut和Scaldi