2011-10-21 12 views
16

私はasmx webserviceに依存性注入を使用し、それを行うためにIoCを使用しようとしている間に立ち往生しました。私は私のWebサービスが私の内部ビジネス層サービスを使用できるようにしたい。 Webサービスは、別のドメインの外部クライアントによって使用され、主に注文や顧客などのエンティティに関する情報の送受信に使用されます。ASMX依存注入とIoC

public class MyService : System.Web.Services.WebService 
{ 
    [WebMethod] 
    public string HelloWorld() 
    { 
     return new MyBusinessService().MyMethod(); 
    } 
} 

public class MyBusinessService : IMyBusinessService 
{ 
    public string MyMethod() 
    { 
     return "hello"; 
    } 
} 

は、私は私のサービスアップ「NEWING」の必要性を排除するために、依存性注入を使用したいが、私はこれを行う方法を見つけ出すカント:

例は次のようになります。私は貧しい人のDIを使ってそれを稼働させることができます。あるいは、少なくとも「貧乏人」と呼ばれると思います。

このような

public class MyService : System.Web.Services.WebService 
{ 
    private IMyBusinessService _myService; 

    public MyService(IMyBusinessService myService) 
    { 
     _myService = myService; 
    } 

    public MyService() : this(new MyBusinessServie()) { } 

    [WebMethod] 
    public string HelloWorld() 
    { 
     return _myService.MyMethod(); 
    } 
} 

しかし、私は、パラメータなしのコンストラクタをせずに実行するためのサービスを得るカントので、私は単に私の依存関係を注入するIoCコンテナを使用する方法のまわりで私の頭を取得傾けます。 親切にしてください、私は経験豊富なプログラマーではなく、依存関係注入をテストし始めました。構造マップを使って私のWindowsフォームアプリケーションでうまく動作するようになっていますが、これに固執しました。

答えて

33

残念ながら、ASP.NETのWebサービスでコンストラクタインジェクションを実行する方法はありません。既定のコンストラクタを提供することはASP.NETの要件です。 MyServiceのコンストラクタは、DIコンテナを使用せずに、このタイプのWebサービスで取得できるコンポジションルートとほぼ同じです。

ASP.NETでは、複数の合成ルートを持つことは珍しいことではありません。個々のWebサービスとWebページのコンストラクタになることができます。 ASP.NET MVCを使用している場合、それはControllerFactoryであり、よりDIに優れています。

実装では、Webサービスからオブジェクトグラフの構成を移動することは重要ではありません。これは、構成ルートであるためです。主なやり方は、Webサービスを可能な限り薄くし、ロジックのほとんどを依存関係に保ち、テストや再利用ができるようにすることです。 HTTPヘッダーから情報を引き出すことは、Webサービスがその情報を依存関係に渡すことができるタスクの例です。

DIパターンとテクニックについては、Mark SeemannのDependency Injection in .NETです。

Webサービスを使用すると、そのようなあなたのDIを実装することができ代わりSystem.Web.Services.WebService由来のSystem.Web.IHttpHandlerを実装した場合:

Global.ashx.cs

public class Global : HttpApplication 
{ 
    protected void Application_PreRequestHandlerExecute(object sender, EventArgs e) 
    { 
     var context = ((HttpApplication)sender).Context; 

     var needsMyBusinessService = context.Handler as INeedMyBusinessService; 
     if (needsMyBusinessService != null) 
      needsMyBusinessService.MyBusinessService = new MyBusinessService(); 
    } 
} 

MyService.ashx.cs

public class MyService : IHttpHandler, INeedMyBusinessService 
{ 
    public IMyBusinessService MyBusinessService { get; set; } 

    public bool IsReusable { get { return true; } } 

    public void ProcessRequest(HttpContext context) 
    { 
     // uses my dependency 
    } 
} 

INeedMyBusinessService.cs

この実装でのキャッチはつまりあるしかし

PreRequestHandlerExecuteイベントがProcessRequestが呼び出される前の最後のイベントである、コールされた後まで、初期化されていないWebサービスオブジェクトとしてSystem.Web.Services.WebServiceを実装するWebサービスとのない作業を行います。

上記の例は、Webサービスごとに一意のインスタンスを作成する場合に機能します。

public class Global : HttpApplication 
{ 
    private static IMyBusinessService businessService; 

    protected void Application_Start(object sender, EventArgs e) 
    { 
     Global.businessService = new MyBusinessService(); 
    } 

    protected void Application_PreRequestHandlerExecute(object sender, EventArgs e) 
    { 
     var context = ((HttpApplication)sender).Context; 

     var needsMyBusinessService = context.Handler as INeedMyBusinessService; 
     if (needsMyBusinessService != null) 
      needsMyBusinessService.MyBusinessService = Global.businessService; 
    } 
} 
:あなたはGlobal.ashx.csがそうのようなファイル実装することができ、各Webサービス要求のための MyBusinessServiceの(シングルトンのライフサイクル)同じインスタンスを持っていると思った場合