5

Global.aspx に次のコードがあります。

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

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

次の Ninject モジュールもあります。

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

ベースコントローラーもあります:

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

このコードは機能します。私が抱えている問題は、ベースコントローラーから inject 属性を削除し、代わりに Ninject ServiceModule でこれを指定したいということです。つまり、Ninject に ProductService をベース コントローラーのプロパティに挿入するように指示するバインディング ルールを ServiceModule に記述するにはどうすればよいでしょうか。

属性を削除すると、NullReferenceException が発生します。

4

2 に答える 2

3

コンベンションベースのバインディングはhttp://github.com/ninject/ninject.extensions.conventionsにあります-1つは実装しIBindingGeneratorます。ただし、これは主にインターフェイスとサービスの検出に関係しています。

一般に、コンストラクターインジェクションは適切なデフォルトのアプローチです。ただし、ASP.NET MVCの動作方法により、これを実行するのが難しくなります(したがって、FubuMVCなど)。したがって、プロパティインジェクションは次善のオプションです。

で使用OnActivationするBindと十分なことができる場合があります。可能であれば、これがはるかに簡単です。

私はあなたがやろうとしていることをコンベンションベースのアクティベーションとして特徴づけます。問題は次のとおりです。

  • 自動注入するものを決定します。具体的ではないものをすべて公開するつもりですか?あなたのカーネルが知っていることはすべて?やりたいことを明確に定義できない限り、注入プロセスは予測不可能になり、理解しにくくなる可能性があります。結局、デバッグして同僚にたくさん説明することになります。

  • それを効率的にします。Ninjectは、インスタンスのアクティブ化を効率的にするために、バックグラウンドで動的にコードを生成します(つまり、マーカーを探してクラスを歩くときに、[Inject]コードを1回生成して、それを実行するためにコードを生成します。

コードを見ると、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 に答える