1

私は大規模なレガシーC#アプリケーションで作業しています。私に割り当てられたタスクは、静的なファクトリクラスServiceLocator.GetObject<T>()のすべての用途を削除し、全体を通してコンストラクタに挿入された依存関係で置き換えます。拡張メソッドでFactoryクラスが必要です

ほとんどの場合、これは簡単ですが、アプリケーションのコードベースには約50のケースがあり、これはややこしいことです。たとえば、Servicelocatorは、静的なクラス、または拡張メソッド、またはWPF MarkupExtension!でも使用されます。

たとえば、このようなコードスニペットに直面した場合はどうしますか? ServiceLocator.GetObject()メソッド上記(離れて叫びから)

public static class MyExtensions 
{ 
    private static ISingletonServiceOne _ServiceOne = null; 
    private static ISingletonServiceTwo _ServiceTwo = null; // etc ... 

    public static SummaryHeader GetBannerSummary(this IModel rfq, object requester) 
    { 
     Guard.ArgumentNotNull(rfq, "rfq"); 
     Guard.ArgumentNotNull(requester, "requester"); 

     if (_ServiceOne == null) 
     { 
      _ServiceOne = ServiceLocator.GetService<ISingletonServiceOne>(requester); 
      Guard.ArgumentNotNull(_ServiceOne, "_ServiceOne"); 
     } 

     return _ServiceOne.GetBannerSummary(rfq); 
    } 

シングルトン登録されたサービスを見つけて、その使用IModelを上の方法を実行するようにIModelを上に拡張メソッドで使用されてきました。

質問です:

  • は、この種のものを避けるために任意のパターン/プラクティスがあります - 静的クラスで必要なDIコンテナは
  • 、値コンバータまたは拡張メソッド任意のパターンがあります/ DIの循環依存性を扱うためのプラクティス?
  • 良いコードと配送時間との間にはトレードオフがありますが、上記で何をしますか?私はこのケースで拡張子のみIModelを外にGetBannerSummary()メソッドを移動するために考えています

は、しかし、(笑っていない)ValueConverters(WPF)とMarkupExtensionsに使用されている同じのServiceLocatorの場合もあります:0

あなたのご意見/ご提案は私が今までのServiceLocatorを使用する唯一の時間は、静的メソッドである例えば

答えて

2

を高く評価しました拡張メソッド、およびIValueConvertersなど、残念ながら依存関係を取得するための他の方法はありません。

ServiceLocatorの呼び出しを遅延ロードされたプロパティに移動するだけで、単体テスト時に依存関係を注入できるようにすることが、ほんのわずかの方が解決策です。

ただし、リクエスタプロパティがGetServiceに渡されても、そのリクエスタオブジェクトを渡すことができるIServiceOneFactory依存関係を追加する必要があります。だから、:

public interface IServiceOneFactory 
{ 
    ISingletonServiceOne Create(object requester); 
} 

public static class MyExtensions 
{ 
    public static IServiceOneFactory ServiceOneFactory 
    { 
     get 
     { 
      if(_ServiceOneFactory==null) 
       _ServiceOneFactory = ServiceLocator.GetService<IServiceOneFactory>(); 
      return _ServiceOneFactory; 
     } 
     set { _ServiceOneFactory = value; } 
    } 

    private static IServiceOneFactory _ServiceOneFactory = null; 
    private static ISingletonServiceOne _ServiceOne = null; 
    private static ISingletonServiceTwo _ServiceTwo = null; // etc ... 

    public static SummaryHeader GetBannerSummary(this IModel rfq, object requester) 
    { 
     Guard.ArgumentNotNull(rfq, "rfq"); 
     Guard.ArgumentNotNull(requester, "requester"); 

     if (_ServiceOne == null) 
     { 
      _ServiceOne = ServiceOneFactory.Create(requester); 
      Guard.ArgumentNotNull(_ServiceOne, "_ServiceOne"); 
     } 

     return _ServiceOne.GetBannerSummary(rfq); 
    } 
} 
+0

こんにちは、回答ありがとうございます。私はRequestorを内部的に編集してServiceLocatorの実装は実際には何もしません!予後に同意する。私がここで扱っているスパゲッティのかなりショッキングなウェブなので、それを解消するための提案は歓迎です:) –

+0

こんにちはアンドリュー、あなたは歓迎です - 私たちはすべてそれを通過しなければなりません!私はあなたがすべてのことを正しくやっていると思うが、私はServiceLocatorの静的、拡張などの方法については見ていない必要に応じて、すべての依存関係をモジュラーにしておけば、それは必要な悪です。 –

+0

はい、大きなリファクタが進行中で、別のプロジェクトのプリズム "モジュール"として大きなコードを再利用する必要があります。私がそれを聞いたときの反応は "笑"でした。とにかくServiceLocatorの120の使用のうち、私は60に下がった。私はもっとトリムすることができると思うが、いくつかは、「イージー・アイ」の解決策がなければ残っているかもしれない。多くのありがとう –

2

は、それはあなたのクラスにIServiceXを注入の代わりに、静的アクセサクラスを使用するためのオプションですか?おそらくGetBannerSummaryメソッドは、IModelを実装する抽象基本クラスの一部にしますか?

オブジェクトのインスタンス化を制御していないときは、DIは飛ばない。 WPFのトリガ、ビヘイビア、またはマークアップ拡張は、そのカテゴリに分類されます。そこにServiceLocatorを使用するオプションはありません。

+0

私はワトソンを疑っているようにうーん...私はこのスパゲッティを解くためにひどくたくさんの仕事をしなければならないようだ –

関連する問題