泛型接口的多个绑定错误
本文关键字:绑定 错误 泛型接口 | 更新日期: 2023-09-27 18:18:47
我使用的是Ninject v2.2.1.4,所以我不确定这是否是新版本的Ninject的工作方式。
我将使用一个经典的继承例子,Animal。所以我有一个基本的抽象Animal
类,然后是无数的Animal
实现。
public abstract class Animal { }
public class Tiger : Animal { }
现在我有一个IValidator
为Animal
,以确保属性设置正确。
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。