泛型接口的多个绑定错误

本文关键字:绑定 错误 泛型接口 | 更新日期: 2023-09-27 18:18:47

我使用的是Ninject v2.2.1.4,所以我不确定这是否是新版本的Ninject的工作方式。

我将使用一个经典的继承例子,Animal。所以我有一个基本的抽象Animal类,然后是无数的Animal实现。

public abstract class Animal { }
public class Tiger : Animal { }

现在我有一个IValidatorAnimal,以确保属性设置正确。

public interface IValidator<T>
{
    bool Validate(T object);
}

对于Animal的每个实现(老虎,猫,狗等)我可能或可能没有IValidator<T>的实现。当没有特定动物的验证器时,我想使用一个默认的验证器来验证基本的Animal属性(IValidator<Animal>)。

下面是IValidator<T>的一些实现,包括默认实现:
// Contains default logic for base Animal inherited by all validators
public abstract class AbstractAnimalValidator<TAnimal> : IValidator<TAnimal> where TAnimal : Animal { }
// Default implementation for IValidator when the animal doesn't have a validator. 
//This just calls the base abstract validator logic.
public DefaultAnimalValidator : AbstractAnimalValidator<Animal> { }
// Validator for a Tiger. It calls the base validate method and then validates properties specific to a Tiger.
public TigerValidator : AbstractAnimalValidator<Tiger> { }

让我们假设老虎是唯一拥有自己验证器的动物。我将有这两个绑定:

Bind<IValidator<Animal>>().To<DefaultAnimalValidator>();
Bind<IValidator<Tiger>>().To<TigerValidator>();

所以现在我将有一个逻辑,试图注入一个验证器为特定的动物,通过尝试获得一个实现,如注入IValidator<Tiger>。如果它不存在,它使用IValidator<Animal>注入默认的验证器。

问题是,当试图注入IValidator<Tiger>时,上述两个绑定都匹配,所以我得到了多个绑定发现错误。这是因为Tiger继承自Animal,所以Tiger既是Tiger又是Animal。我已经想出了一些hack的解决方案,但有没有什么我错过了?

泛型接口的多个绑定错误

可以修改IValidator<T>接口吗?如果是,您可以将类型参数标记为逆变:

public interface IValidator<in T>
{
    bool Validate(T o);
}

它将允许您将IValidator<Animal>分配给IValidator<Tiger>。然后,您可以显式指定所有绑定:

Bind<IValidator<Cat>>().To<DefaultAnimalValidator>();
Bind<IValidator<Dog>>().To<DefaultAnimalValidator>();
Bind<IValidator<Tiger>>().To<TigerValidator>();

与隐式回退到IValidator<Animal>相比,这种方法还有一个很大的优势。如果您添加了另一个从Animal派生的类,并带有它自己的验证器,而忘记添加绑定,那么您将得到一个运行时错误。如果您使用Bind<IValidator<Animal>>().To<DefaultAnimalValidator>(),您将得到一个难以跟踪的bug。