5

我的 Global.aspx 中有以下代码

protected override void OnApplicationStarted()
{
    AreaRegistration.RegisterAllAreas();
    RegisterRoutes(RouteTable.Routes);
    RegisterAllControllersIn(Assembly.GetExecutingAssembly());
}

protected override IKernel CreateKernel()
{
    return new StandardKernel(new ServiceModule());
}

我还有以下忍者模块:

internal class ServiceModule : NinjectModule
{
    public override void Load()
    {
        Bind<IProductService>().To<ProductService>().InRequestScope();
    }
}

我还有一个基本控制器:

public class BaseController : Controller
{
    [Inject]
    public IProductService ProductService
    {
        get;
        set;
    }
}

此代码有效。我遇到的问题是我想从基本控制器中删除注入属性并在 Ninject ServiceModule 中指定它。换句话说,我将如何在 ServiceModule 中编写一个绑定规则,告诉 Ninject 将 ProductService 注入基本控制器的属性中?

如果我删除该属性,我将得到一个 NullReferenceException。

4

2 回答 2

3

基于约定的绑定存在于http://github.com/ninject/ninject.extensions.conventions - 一个实现IBindingGenerator。不过,这主要与发现接口和服务有关。

一般来说,构造函数注入是一种很好的默认方法。然而,ASP.NET MVC 的工作方式使得这更难做到(因此 FubuMVC 等)。所以属性注入是下一个最佳选择。

您可能会发现使用OnActivationin yourBind可能会让您做得足够多——如果可以的话,这是迄今为止最简单的。

我会将您尝试做的事情描述为基于约定的激活。问题是:

  • 决定要自动注入的内容。你要注入所有不具体的公开内容吗?你的内核知道的一切?除非你能对你想要做的事情提出一个清晰的定义,否则注入过程可能会变得不可预测且难以理解。你最终要调试并向同事解释很多。

  • 使其高效。Ninject 在幕后动态生成代码以使实例的激活有效(即,在遍历类寻找[Inject]标记时,它会生成一次代码来执行该操作,然后就像您以手写方式编写它一样被jitted)。

查看代码,没有简单的 OOTB 方法。看起来像添加一个自定义IInjectionHeuristic就可以了。

但是,如果您要深入到容器中,则需要

  1. 停下来看看你是否可以通过不走这条路来保持简单
  2. 转到ninject邮件列表并搜索类似的东西
  3. 如果您仍然想这样做,请在那里发送邮件。
于 2010-07-01T09:20:40.353 回答
2

扩展 Ruben Bartelink 的想法,您可以创建 IInjectionHeuristic 的自定义实现

public class ControllerInjectionHeuristic : NinjectComponent, IInjectionHeuristic
{
    private readonly IKernel kernel;

    public BaseControllerInjectionHeuristic(IKernel kernel)
    {
        this.kernel = kernel;
    }

    public bool ShouldInject(MemberInfo member)
    {
        if (member.ReflectedType != typeof(BaseController))
        {
            return false;
        }

        var propertyInfo = member.ReflectedType.GetProperty(member.Name);
        object service = kernel.TryGet(propertyInfo.PropertyType);

        return service != null;
    }
}

ControllerInjectionHeuristic它将注入BaseController内核能够解析服务的任何属性(服务)。

向内核注册自定义实现。

var kernel = new StandardKernel();
kernel.Components.Add<IInjectionHeuristic, ControllerInjectionHeuristic>();

该问题的另一个解决方案是使用OnActivation. (此解决方案未经测试,但它应该让您了解如何进行)。

public class ControllerModule : NinjectModule
{
    public override void Load()
    {
        // Get all controller types. You could use
        // Ninject.Extensions.Conventions.
        IEnumerable<Type> controllerTypes = null;
        foreach (var controllerType in controllerTypes)
        {
            Bind(controllerType).ToSelf().InRequestScope()
                .OnActivation(ControllerActivation);
        }
    }

    private static void ControllerActivation(IContext context, object obj)
    {
        var controller = obj as BaseController;
        if (controller == null)
        {
            return;
        }

        controller.ProductService = context.Kernel.Get<IProductService>();
    }
}
于 2011-06-06T19:59:46.160 回答