首页 文章

当具体类型派生自抽象基类时,Ninject无法解析接口类型

提问于
浏览
4

我有一个Ninject尝试解决接口类型的问题,其中具体类型派生自实现接口的抽象基类 .

EDIT: This is on Windows Mobile using .NET CF.

我的特殊问题涉及演示者和视图,所以我坚持在这个例子而不是foos和bar .

我想为演示者和视图注入工厂,以允许在UI视图堆栈深处创建这些实例 .

下面我省略了所有错误检查以获得更好的可读性 .

我的工厂界面:

public interface IFactory<T>
{
    T Create();
}

我的主持人和观点:

public sealed class Presenter
{
    private readonly View view;

    public Presenter(View view)
    {
        this.view = view;
    }
}

public sealed class View
{
    public View()
    {
    }
}

首先,我将展示Ninject按预期结算的完美功能 . 这不包括我在开头提到的抽象基类 . 在此之后,我将添加对抽象基类的轻微修改,这将在尝试解析依赖项时使Ninject抛出 .

我们在上面看到,演示者依赖于视图,因此演示者工厂将依赖于视图工厂:

public sealed class GoodPresenterFactory : IFactory<Presenter>
{
    private readonly IFactory<View> viewFactory;

    public GoodPresenterFactory(IFactory<View> viewFactory)
    {
        this.viewFactory = viewFactory;
    }

    public Presenter Create()
    {
        return new Presenter(this.viewFactory.Create());
    }
}

public sealed class ViewFactory : IFactory<View>
{
    public ViewFactory()
    {
    }

    public View Create()
    {
        return new View();
    }
}

与Ninject联系:

Bind<IFactory<Presenter>>().To<GoodPresenterFactory>();
Bind<IFactory<View>>().To<ViewFactory>();

然后解决演示者工厂:

var presenterFactory = container.Get<IFactory<Presenter>>();

到目前为止,一切都很完美 . 对演示者工厂内视图工厂的依赖性按预期解决 .

现在,我有一百万个看起来像上面的GoodPresenterFactory的类,因此我想要一个小的基类来处理一些琐碎的常见内容,比如对presenter工厂中视图工厂的依赖:

public abstract class FactoryBase<T, U> : IFactory<T>
{
    protected readonly U dependency;

    protected FactoryBase(U dependency)
    {
        this.dependency = dependency;
    }

    public abstract T Create();
}

然后,演示者工厂将发生变化,该变更中的某些内容将使Ninject无法解决:

public sealed class BadPresenterFactory : FactoryBase<Presenter, IFactory<View>>
{
    public BadPresenterFactory(IFactory<View> viewFactory)
        : base(viewFactory)
    {
    }

    public override Presenter Create()
    {
        return new Presenter(this.dependency.Create());
    }
}

并相应地更改Ninject接线:

Bind<IFactory<Presenter>>().To<BadPresenterFactory>();
Bind<IFactory<View>>().To<ViewFactory>();

这些更改将使Ninject在执行时抛出ArgumentNullException

var presenterFactory = container.Get<IFactory<Presenter>>();

从例外调用堆栈:

at System.Reflection.RuntimeMethodInfo.GetParentDefinition()
at System.Reflection.CustomAttribute.IsDefined(MemberInfo member, Type caType, Boolean inherit)
at System.Reflection.RuntimeMethodInfo.IsDefined(Type attributeType, Boolean inherit)
at System.Attribute.IsDefined(MemberInfo element, Type attributeType, Boolean inherit)
at System.Attribute.IsDefined(MemberInfo element, Type attributeType)
at Ninject.Infrastructure.Language.ExtensionsForMemberInfo.HasAttribute(MemberInfo member, Type type)
at Ninject.Selection.Heuristics.StandardInjectionHeuristic.ShouldInject(MemberInfo member)
at Ninject.Selection.Selector.<>c__DisplayClassa.<SelectMethodsForInjection>b__9(IInjectionHeuristic h)
at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source, Func`2 predicate)
at Ninject.Selection.Selector.<SelectMethodsForInjection>b__8(MethodInfo m)
at System.Linq.Enumerable.<WhereIterator>d__0`1.MoveNext()
at Ninject.Planning.Strategies.MethodReflectionStrategy.Execute(IPlan plan)
at Ninject.Planning.Planner.<>c__DisplayClass2.<GetPlan>b__0(IPlanningStrategy s)
at Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map[T](IEnumerable`1 series, Action`1 action)
at Ninject.Planning.Planner.GetPlan(Type type)
at Ninject.Activation.Providers.StandardProvider.Create(IContext context)
at Ninject.Activation.Context.Resolve()
at Ninject.KernelBase.<Resolve>b__4(IContext context)
at System.Linq.Enumerable.<SelectIterator>d__d`2.MoveNext()
at System.Linq.Enumerable.<CastIterator>d__b0`1.MoveNext()
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
at Ninject.ResolutionExtensions.Get[T](IResolutionRoot root, IParameter[] parameters)
at NinjectTest.Program.Main()

如果我修改 FactoryBase 以使它没有依赖,它只是一个裸基类,那么Ninject也会失败 .

public abstract class NakedFactoryBase<T> : IFactory<T>
{
    protected NakedFactoryBase()
    {
    }

    public abstract T Create();
}

public sealed class PointlessPresenterFactory : NakedFactoryBase<Presenter>
{
    private readonly IFactory<View> viewFactory;

    public PointlessPresenterFactory(IFactory<View> viewFactory)
    {
        this.viewFactory = viewFactory;
    }

    public override Presenter Create()
    {
        return new Presenter(this.viewFactory.Create());
    }
}

正如您所看到的那样,除了 GoodPresenterFactory 中的直接 IFactory<Presenter> 实现之外, PointlessPresenterFactory 的失败与后续 GoodPresenterFactory 相同,而 PointlessPresenterFactory 中使用的是完整的裸基类 .

知道为什么Ninject在使用工厂基类时无法解决?

1 回答

  • 3

    此问题已在构建版本2.3.0.46中得到修复,并将成为下一版本(2.4)的一部分 .

    注意:因为CF似乎不允许检测方法是通用的,或者不能再在基本方法上定义Inject属性 . 它必须在重载方法上定义 .

相关问题