通用接口

时间:2015-10-21 19:39:32

标签: c# .net ninject

我使用的是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同时属于TigerAnimal。我已经围绕这个提出了一些愚蠢的解决方案,但是我有什么遗漏?

1 个答案:

答案 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>(),则会遇到难以追踪的错误。