5

基本クラスで定義された依存プロパティがあり、その派生クラスのコンストラクター内で使用しようとしていますが、機能しません。プロパティが null として表示されます。Unity は、container.Resolve(); でインスタンスを解決した後に依存プロパティを解決します。

私が持っている 1 つの代替手段は、IUnityContainer パラメーターを MyViewModel クラス コンストラクターに追加し、ILogger プロパティ my self を次のように設定することです。

public MyViewModel(IUnityContainer container)
{
  Logger = container.Resolve<ILogger>();
}

編集: @ Wiktor_Zychla による別の提案は、コンストラクターによって注入されたパラメーターを次のように渡すことです。

public MyViewModel(ILogger _logger)
{
    Logger = _logger;
}

これはうまくいくように見えますが、派生したすべてのViewModelに対してそれを行う必要があります..

しかし、基本クラスで注釈付きの ILogger 依存関係を使用していません。以下の私のクラスのサンプルを参照してください。問題は、どの代替案があるか、または何が間違っているかです。

ありがとう!

次のような ViewModel 基本クラスがあります。

public abstract class ViewModelBase
{
    [Dependency]
    public ILogger Logger { get; set; }
....
}

それから私はそれを派生させるクラスを持っています:

public class MyViewModel : ViewModelBase
{
    public MyViewModel()
    {
         //I want to use my dependent property in constructor, but doesn't 

         Logger.Error("PRINT AN ERROR");
    }
}

そして、私のアプリケーション エントリ ポイントでは、ILogger をシングルトンとして登録し、MyViewModel クラスを登録しています。

container.RegisterType<ILogger, MyAppLogger>(new ContainerControlledLifetimeManager());
container.RegisterType<MyViewModel>();
4

2 に答える 2

7

Unity は、container.Resolve(); でインスタンスを解決した後に依存プロパティを解決します。

あなたがそれについて考えるならば、これは非常に明白です。これを手動で実行してみてください。あなたは成功しません。プロパティを注入できるようにするには、インスタンスが必要です。インスタンスがあるということは、コンストラクターが呼び出されたことを意味します。

コンストラクターでやりすぎているために問題が発生します。依存性注入の観点からは、コンストラクターはその依存性を受け入れ (それらが null でないことを確認する)、それらをプライベート フィールドに格納するだけである必要があります。これ以上のことをするのはアンチパターンです。コンストラクターにはロジックを含めないでください。

コンストラクターにロジックがあると、オブジェクト グラフの作成は信頼できなくなりますが、オブジェクト グラフの作成は高速で信頼できるものでなければなりません。

ビジネスロジックを実行すると、クラスは完全にインスタンス化されるため、この原則に従えば問題はありません。コンストラクターはプライベート フィールドを設定するだけであるため、問題が発生することはなく、呼び出しを行う理由もありませんLogger.Error("PRINT AN ERROR");

于 2012-06-20T20:55:11.150 に答える
2

1) をドロップするだけで、すべてのビューモデルでロガーの異なるインスタンスを使用できますContainerControlledLifetimeManager

2)Type登録時に指定することで、ビューモデルごとに異なるロガーを登録できます。

container.RegisterType<ILogger, MyAppLogger>();
container.RegisterType<ILogger, MyOtherLogger>("uniqueNameOfAnILoggerRegistration);
container.RegisterType<MyViewModel>(new InjectionConstructor(
    new ResolvedParameter(typeof(ILogger), "uniqueNameOfAnILoggerRegistration")));

コンストラクター注入を使用すると、ビューモデルに の新しいインスタンスが注入されますMyOtherLogger

プロパティ注入は「あると便利な」値のために予約する必要があり、クラスは明らかにロガーの存在に依存しているため、ctor インジェクションを使用することを強くお勧めします。

于 2012-06-20T19:49:57.140 に答える