我使用的是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
(Tiger,Cat,Dog等等)的每个实现,我可能会或可能不会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
。我已经围绕这个提出了一些愚蠢的解决方案,但是我有什么遗漏?
答案 0 :(得分:1)
您可以修改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>()
,则会遇到难以追踪的错误。