1

コントローラーコンストラクターにロールインした「共通の」作業があるMVC3コントローラーがあります。その一般的な作業の一部は、Unity を介して動的に解決される疎結合クラス (たとえばourService) によって行われます (IoC / 依存性注入用)。ourServiceコントローラーのコンストラクターでは null (つまり、解決されていません) ですが、通常のコントローラー メソッドでは適切に解決されます。以下の簡単なデモ コードは、問題を示しています。

public class Testing123Controller : BaseController
{
    [Dependency]
    public IOurService ourService { get; set; }

    public Testing123Controller()
    {
            ourService.SomeWork(1); // ourService=null here !!
            ...
    }

    public ActionResult Index()
    {
            ourService.SomeWork(1); // resolved properly here here !!
            ...
    }
    ...
}

質問:

  1. Unity の解決動作にこの違いがあるのはなぜですか? 私は一貫した行動を期待します。
  2. コントローラーのコンストラクターでも Unity がこれを解決するように修正するにはどうすればよいですか?

Unity 2.0 をセットアップした方法は次のとおりです。

Global.asax

Application_Start()
{
    ...
    Container = new UnityContainer();
    UnityBootstrapper.ConfigureContainer(Container);
    DependencyResolver.SetResolver(new UnityDependencyResolver(Container));
    ...
}

public static void ConfigureContainer(UnityContainer container)
{
    ...
    container.RegisterType<IOurService, OurService>();
    ...
}

IOurService.cs

public interface IOurService
{
    bool SomeWork(int anInt);
}

OurService.cs

public class OurService: IOurService
{
    public bool SomeWork(int anInt)
    {
        return ++anInt; //Whew! Time for a break ...
    }
}
4

3 に答える 3

5

クラスの基本原則として、インスタンス プロパティを設定する前に、インスタンスをインスタンス化する必要があります。

Unity は依存関係プロパティを設定する必要がありますが、インスタンスが完全にインスタンス化されるまでは設定できません。つまり、コンストラクターの実行が完了する必要があります。

コンストラクターで依存関係プロパティを参照している場合、これは時期尚早です。Unity がまだそれを設定する方法がないため、設定解除されます (つまり、null)。

コンストラクターで依存関係を使用する必要がある場合は、コンストラクター インジェクションを使用する必要があります。一般的には、コンストラクター注入を使用する方が通常はより良い方法です。

public class Testing123Controller : BaseController
{
    public IOurService ourService { get; set; }

    public Testing123Controller(IOurService ourService)
    {
            this.ourService = ourService;
            this.ourService.SomeWork(1); // ourService no longer null here
            ...
    }

    public ActionResult Index()
    {
            ourService.SomeWork(1); // also resolved properly here
            ...
    }
    ...
}

注: この例ourServiceでは、コードの他の部分がアクセスする必要がある場合に備えて、公的に取得および設定可能なプロパティとして残しました。一方、クラス内でのみアクセスされる場合 (Unity の目的でのみ公開されていた場合) は、コンストラクター インジェクションの導入により、それをprivate readonlyフィールドにするのが最善です。

于 2012-12-09T01:35:16.497 に答える
1

コンストラクターインジェクションではなくプロパティインジェクション(Dependency属性を使用)を使用しているため、コントローラーがインスタンス化されるまで依存関係は解決されません。依存関係がコンストラクターであることにアクセスしたい場合は、それをctorに追加するだけです。

private readonly IOurService _ourService { get; set; }

public Testing123Controller(IOurService ourService)
{
  _ourService = ourService;
  _ourService.SomeWork(1); // ourService=null here !!
  ...
}
于 2012-12-09T01:24:04.707 に答える
0

Unityがコンストラクターで動作するには、インスタンス自体がUnityを使用して解決される必要があるのではないかと思います。Serviceプロパティがnullコンストラクターにあるという事実は、この考えをサポートしています。(Unityではなく)自分でコントローラーを呼び出すと、Unityはプロパティを解決する時間がありません。

于 2012-12-09T01:24:30.590 に答える