2011-01-19 11 views
5

REST WCFサービス(Windows Server 2008)にIoCサポートを追加しようとしています。私はこれに新しいですし、下のビデオで提供される指示に従っています:WCFサービスにIoCサポートを追加しようとしています

http://www.dimecasts.net/Content/WatchEpisode/150

ビデオは私がのStructureMapのIoCのアップとWCFエンドポイントを露出させながら実行する手助けクラスの数をウォークスルー。私はこの記事の最後にすべてのコードを掲載しました。

私は私のコードを実行すると、カスタムクラスStructureMapServiceHostは、メソッド(ウリは[] BASEADDRESS paramsは、型サービス種別)StructureMapServiceHost @エラーがスローされます:

public class StructureMapServiceHost : ServiceHost 
{ 
    public StructureMapServiceHost() {} 

    public StructureMapServiceHost(Type serviceType, params Uri[] baseAddress) 
     : base(serviceType, baseAddress) 
    { 

    } 

    protected override void OnOpening() 
    { 
     Description.Behaviors.Add(new IoCServiceBehavior()); 
     base.OnOpening(); 
    } 
} 

私がいることを言われています指定されたサービスタイプは、デフォルトの(パラメーターがない)コンストラクターがないため、サービスとしてロードできませんでした。問題を解決するには、型にデフォルトのコンストラクタを追加するか、型のインスタンスをホストに渡します。

これは当てはまりません。しかし、ビデオの例はどちらも持っていませんでした。以下は私のサービスです

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] 
    public class UserService : IUserService 
    { 
     public UserService(IUserRepository specification) 
     { 
      Specification = specification; 
     } 

     public List<User> GetAllUsers() 
     { 
      return Specification.GetAllUsers(); 
     } 

     public User GetUser(string userId) 
     { 
      return Specification.GetUserById(new Guid(userId)); 
     } 

     private List<User> SearchForUsers(string searchString) 
     { 
      return Specification.SearchUsers(searchString); 
     } 

     public IUserRepository Specification { get; set; } 

    } 



public class IoCServiceBehavior : IServiceBehavior 
    { 
     public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
     { 
     } 

     public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, 
      Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) 
     { 
     } 

     public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
     { 
      foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers) 
      { 
       new StructureMapInstanceProvider(serviceDescription.ServiceType); 
      } 
     } 
    } 


public class StructureMapInstanceProvider : IInstanceProvider 
{ 
    private readonly Type _serviceType; 

    public StructureMapInstanceProvider(Type serviceType) 
    { 
     _serviceType = serviceType; 
    } 

    public object GetInstance(InstanceContext instanceContext) 
    { 
     return GetInstance(instanceContext, null); 
    } 

    public object GetInstance(InstanceContext instanceContext, Message message) 
    { 
     var instance = ObjectFactory.GetInstance(_serviceType); 

     return instance; 
    } 

    public void ReleaseInstance(InstanceContext instanceContext, object instance) 
    { 
     throw new NotImplementedException(); 
    } 
} 




public class StructureMapServiceHostFactory : ServiceHostFactory 
    { 
     public StructureMapServiceHostFactory() 
     { 
      IoCBootstrap.SetupIoc(); 
     } 

     protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) 
     { 
      return new StructureMapServiceHost(serviceType, baseAddresses); 
     } 
    } 

アイデアはありますか?ありがとう。 *

EDIT * ** * ** * ** * ** * ** * ** * ** * ** * * * ****

投稿者:StructureMapServiceHost:

public StructureMapServiceHost(Type serviceType, params Uri[] baseAddress) 
      : base(serviceType, baseAddress) { } 

、コメントを追加しました:その後、

public StructureMapServiceHost(Object singletonInstance, params Uri[] baseAddress) 
      : base(singletonInstance, baseAddress) { } 

そして、私のUserServiceのコンストラクタからパラメータを削除します。私は今(インターネット上の制約を)ビデオを見てみることができない

The HTML document does not contain Web service discovery information.

答えて

0

が、私は彼らの例では、クラスがで任意のコンストラクタを持っていなかったかなり確信している:私はエラーを取得しておりませんすべて。その場合、コンパイラはあなたのために空のパラメータのないコンストラクタを生成します。そのため、クラスにデフォルトのコンストラクタがありました。

限りかなり簡単思わ例外として:あなたのパラメータなしのコンストラクタはSpecificationプロパティを初期化しないので、それは常にnullです - あなたはあなたの方法でそれにアクセスしようとしたら、当然、NullReferenceExceptionの原因となります。

あなたがここで意図したのは、UserServiceオブジェクトを自分で作成してIUserRepositoryを渡すことです。

この場合、ServiceHostのコンストラクタのオーバーロードは、Typeの代わりにobjectを使用する方がよいでしょう。そうすれば、UserServiceオブジェクトを完全に制御でき、デフォルトのコンストラクタはまったく必要ありません。

+0

おかげフョードル。私はあなたが提案したことを試して、新しいエラーを得ました。私の上のEDITを見てください。私が間違っていることを教えてくれますか?コードイラストはこの時点で助けになるかもしれません。 –

+0

@Code Sherpa:あなたのブラウザでそのサービスにアクセスして、それがどのようなエラーを表示するかを確認してください。 –

+0

こんにちはFydor - 私は取得しています:リソースが見つかりません。 説明:HTTP 404。探しているリソース(またはその依存関係の1つ)が削除されているか、名前が変更されているか、一時的に使用できない可能性があります。次のURLを確認し、正しく入力されていることを確認してください。 リクエストされたURL:/Users.svc/users –

17

あなたのサービスがInstanceContextMode.SingleCallとWCFチームはInstanceContextModeがあるときのSingleCall IInstanceProviderは、インスタンスを作成するために呼び出されていないことを、彼らの無限の知恵で、決定している使用しています( - インタフェースdeclrationの見出しの下二パラhttp://blogs.msdn.com/b/carlosfigueira/archive/2011/05/31/wcf-extensibility-iinstanceprovider.aspxを参照してください)。 「これは進行中の作業であり、より良い方法があるかもしれません

using System; 
using System.Collections.Generic; 
using System.ServiceModel; 
using System.ServiceModel.Activation; 
using StructureMap; 
using StructureMap.Pipeline; 
using System.Linq; 

using ServiceHostCreator = System.Func<System.Type, System.Uri[], System.ServiceModel.ServiceHost>; 

namespace x.ServiceExtensions 
{ 
    public class xWebServiceHostFactory : ServiceHostFactory 
    { 
     private readonly IDictionary<InstanceContextMode, ServiceHostCreator> _serviceHostCreators; 

     public xWebServiceHostFactory() 
     { 
      ObjectFactory.Initialize(init => 
             init.Scan(scan => 
                { 
                 scan.AssembliesFromApplicationBaseDirectory(); 
                 scan.IgnoreStructureMapAttributes(); 
                 scan.LookForRegistries(); 
                })); 
      _serviceHostCreators = new Dictionary<InstanceContextMode, ServiceHostCreator> 
             { 
              { InstanceContextMode.PerCall, (t, a) => PerCallServiceHostCreator(t, a) }, 
              { InstanceContextMode.PerSession, (t, a) => PerSessionServiceHostCreator(t, a) }, 
              { InstanceContextMode.Single, (t, a) => SingleInstanceServiceHostCreator(t, a) } 
             }; 
     } 

     protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) 
     { 
      var serviceInstanceContextMode = GetServiceInstanceContextMode(serviceType); 
      var serviceHostCreator = _serviceHostCreators[ serviceInstanceContextMode ]; 
      return serviceHostCreator(serviceType, baseAddresses); 
     } 

     private static InstanceContextMode GetServiceInstanceContextMode(Type serviceType) 
     { 
      var serviceBehaviour = serviceType 
       .GetCustomAttributes(typeof (ServiceBehaviorAttribute), true) 
       .Cast<ServiceBehaviorAttribute>() 
       .SingleOrDefault(); 
      return serviceBehaviour.InstanceContextMode; 
     } 

     private static ServiceHost PerCallServiceHostCreator(Type serviceType, Uri[] baseAddresses) 
     { 
      var args = new ExplicitArguments(); 
      args.Set(serviceType); 
      args.Set(baseAddresses); 
      var serviceHost = ObjectFactory.GetInstance<TelaWebServiceHost>(args); 
      return serviceHost; 
     } 

     private static ServiceHost PerSessionServiceHostCreator(Type serviceType, Uri[] baseAddresses) 
     { 
      return PerCallServiceHostCreator(serviceType, baseAddresses); 
     } 

     private static ServiceHost SingleInstanceServiceHostCreator(Type serviceType, Uri[] baseAddresses) 
     { 
      var service = ObjectFactory.GetInstance(serviceType); 
      var args = new ExplicitArguments(); 
      args.Set(typeof(object), service); 
      args.Set(baseAddresses); 
      var serviceHost = ObjectFactory.GetInstance<TelaWebServiceHost>(args); 
      return serviceHost; 
     } 
    } 
} 

、現時点では私のことができます。Currrently

私は、サービスホストの工場でその周りを取得する理想的な方法よりも少ないを持っています1つを見つける。

+1

InstanceContextModeに関する非常に関連性の高い情報に言及してくれてありがとうございました。私には悲しみの終わりがありませんでした。シングルモードを使用する必要がある場合、シングルインスタンスパラメータを受け入れ、解決されたインスタンスを渡すServiceHostコンストラクタを使用する必要があります。 – Shaun

0

このようなことをしようとしている人には、IoCコンテナとしてSpring.NETを使用することを強く推奨します。他のいくつかのコンテナと同じように使用するのは簡単ではないかもしれませんが(私はXMLの設定が特に好きではありません)、これはWCFの最高の統合です。また、InstanceContextMode.SingleCallの問題(AOP /動的プロキシフレームワークを使用)の賢明で透明な回避策が付属しています。

http://www.springframework.net/docs/1.2.0-M1/reference/html/wcf.html

http://www.springframework.net/doc-latest/reference/html/wcf-quickstart.html

関連する問題