2016-09-06 20 views
1

を持っていないため、提供されるサービスの種類をサービスとしてロードすることができませんでした、私は原因を把握できないために:WCFシングルトン・サービスエラー:それは私がWCFと、次の奇妙な問題を持っているデフォルトコンストラクタ

私はWCFと協力して、プリンタのようなデバイス用に実装する必要があるリモートコントロールAPI用に使用するかどうかを判断しています。このデバイスは、.Netで実装されたコントローラソフトウェアを実行するWindows-PCによって制御されます。このソフトウェアのために私はAPIを実装する必要があります。

サービスはコントローラソフトウェア内から自己ホスティングされていますが、現在、コントローラと一緒に対応するオブジェクト/クラスを使用してこのインスタンスを作成できるように、WCFサービスのシングルトンインスタンスを作成する方法を検討しています-ソフトウェア。私はこれを縮小版を使用して動作させることにしましたが、サービスにデフォルトの(パラメータなしの)コンストラクタが含まれていない場合、この警告が表示されます。さらに奇妙なことに、私は2番目の文で例外が私に言い聞かせている(あるいは少なくとも私は私が思うように思うのですが)正確にやっています。この例外は、タイトルWCF Service Hostと別ウィンドウでスローされ、プログラムはその後正常に実行を継続している。ここで

System.InvalidOperationException: The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor. To fix the problem, add a default constructor to the type, or pass an instance of the type to the host.

at System.ServiceModel.Description.ServiceDescription.CreateImplementation(Type serviceType)

at System.ServiceModel.Description.ServiceDescription.SetupSingleton(ServiceDescription serviceDescription, Object implementation, Boolean isWellKnown)

at System.ServiceModel.Description.ServiceDescription.GetService(Type serviceType)

at System.ServiceModel.ServiceHost.CreateDescription(IDictionary`2& implementedContracts)

at System.ServiceModel.ServiceHostBase.InitializeDescription(UriSchemeKeyedCollection baseAddresses)

at System.ServiceModel.ServiceHost..ctor(Type serviceType, Uri[] baseAddresses)

at Microsoft.Tools.SvcHost.ServiceHostHelper.CreateServiceHost(Type type, ServiceKind kind)

at Microsoft.Tools.SvcHost.ServiceHostHelper.OpenService(ServiceInfo info)

は私がサービスを作成するために使用していたコードです。私はService.csのコメント行に、デフォルトのコンストラクタが含まれているとコメントしました。興味深いことに、デフォルトのコンストラクタをインクルードすると、エラーが発生することはありません。コールされることはありません(ブレークポイントを設定することで確認しました)。あなたはそれをコメント解除しましたが、例外はスローされません。

Server.cs

public class Server 
{ 
    private ServiceHost svh; 
    private Service service; 

    public Server() 
    { 
     service = new Service("A fixed ctor test value that the service should return."); 
     svh = new ServiceHost(service); 
    } 

    public void Open(string ipAdress, string port) 
    { 
     svh.AddServiceEndpoint(
     typeof(IService), 
     new NetTcpBinding(), 
     "net.tcp://"+ ipAdress + ":" + port); 
     svh.Open(); 
    } 

    public void Close() 
    { 
     svh.Close(); 
    } 
} 

Service.cs

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, 
       InstanceContextMode = InstanceContextMode.Single)] 
public class Service : IService 
{ 
    private string defaultString; 

    public Service(string ctorTestValue) 
    { 
     this.defaultString = ctorTestValue; 
    } 


    //// when this constructor is uncommented, I do not get the error 
    //public Service() 
    //{ 
    // defaultString = "Default value from the ctor without argument."; 
    //} 

    public string GetDefaultString() 
    { 
     return defaultString; 
    } 

    public string GetData(int value) 
    { 
     return string.Format("You entered: {0}", value); 
    } 

    public CompositeType GetDataUsingDataContract(CompositeType composite) 
    { 
     if (composite == null) 
     { 
      throw new ArgumentNullException("composite"); 
     } 
     if (composite.BoolValue) 
     { 
      composite.StringValue += "Suffix"; 
     } 
     return composite; 
    } 

    public string Ping(string name) 
    { 
     Console.WriteLine("SERVER - Processing Ping('{0}')", name); 
     return "Hello, " + name; 
    } 

    static Action m_Event1 = delegate { }; 

    static Action m_Event2 = delegate { }; 

    public void SubscribeEvent1() 
    { 
     IMyEvents subscriber = OperationContext.Current.GetCallbackChannel<IMyEvents>(); 
     m_Event1 += subscriber.Event1; 
    } 

    public void UnsubscribeEvent1() 
    { 
     IMyEvents subscriber = OperationContext.Current.GetCallbackChannel<IMyEvents>(); 
     m_Event1 -= subscriber.Event1; 
    } 

    public void SubscribeEvent2() 
    { 
     IMyEvents subscriber = OperationContext.Current.GetCallbackChannel<IMyEvents>(); 
     m_Event2 += subscriber.Event2; 
    } 

    public void UnsubscribeEvent2() 
    { 
     IMyEvents subscriber = OperationContext.Current.GetCallbackChannel<IMyEvents>(); 
     m_Event2 -= subscriber.Event2; 
    } 

    public static void FireEvent1() 
    { 
     m_Event1(); 
    } 

    public static void FireEvent2() 
    { 
     m_Event2(); 
    } 

    public static Timer Timer1; 
    public static Timer Timer2; 

    public void OpenSession() 
    { 
     Timer1 = new Timer(1000); 
     Timer1.AutoReset = true; 
     Timer1.Enabled = true; 
     Timer1.Elapsed += OnTimer1Elapsed; 

     Timer2 = new Timer(500); 
     Timer2.AutoReset = true; 
     Timer2.Enabled = true; 
     Timer2.Elapsed += OnTimer2Elapsed; 
    } 

    void OnTimer1Elapsed(object sender, ElapsedEventArgs e) 
    { 
     FireEvent1(); 
    } 

    void OnTimer2Elapsed(object sender, ElapsedEventArgs e) 
    { 
     FireEvent2(); 
    } 

} 

IServices.cs

public interface IMyEvents 
{ 
    [OperationContract(IsOneWay = true)] 
    void Event1(); 

    [OperationContract(IsOneWay = true)] 
    void Event2(); 
} 

// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together. 
[ServiceContract(CallbackContract = typeof(IMyEvents))] 
public interface IService 
{ 
    [OperationContract] 
    string GetData(int value); 

    [OperationContract] 
    string GetDefaultString(); 

    [OperationContract] 
    CompositeType GetDataUsingDataContract(CompositeType composite); 

    // TODO: Add your service operations here 
    [OperationContract] 
    string Ping(string name); 

    [OperationContract] 
    void SubscribeEvent1(); 

    [OperationContract] 
    void UnsubscribeEvent1(); 

    [OperationContract] 
    void SubscribeEvent2(); 

    [OperationContract] 
    void UnsubscribeEvent2(); 

    [OperationContract] 
    void OpenSession(); 
} 

// Use a data contract as illustrated in the sample below to add composite types to service operations. 
// You can add XSD files into the project. After building the project, you can directly use the data types defined there, with the namespace "WcfService.ContractType". 
[DataContract] 
public class CompositeType 
{ 
    bool boolValue = true; 
    string stringValue = "Hello "; 

    [DataMember] 
    public bool BoolValue 
    { 
     get { return boolValue; } 
     set { boolValue = value; } 
    } 

    [DataMember] 
    public string StringValue 
    { 
     get { return stringValue; } 
     set { stringValue = value; } 
    } 
} 

Mainサーバーを起動するための

static void Main(string[] args) 
{ 
    // start server 
    var server = new Server(); 
    server.Open("localhost", "6700"); 
    Console.WriteLine("Server started."); 

    Console.ReadLine(); 
    server.Close(); 
} 
+0

私はあなたのコードをコピーして、私の環境からそれを実行し、問題は発生しませんでした。 –

+0

VSでデバッグ中にWcfSvcHostが実行されていますか? https://msdn.microsoft.com/en-us/library/bb552363(v=vs.110).aspxを参照してください。 –

+0

@KimJohnsonあなたの提案の後、私はVSの外側(デフォルトではパラメータのないコンストラクタなし)から小さなテストプログラムを起動しようとしましたが、上記のエラーは発生しません。だから私はそれがあなたの提案と関係しているかもしれないと推測しています。あなたが提供したリンクを読んだ後、私はまだ問題が何であるかを理解していません。それ以上の提案はありますか?ところで、私は私の質問で言及することを忘れていました。私が確認したブレークポイントを設定することで、デフォルトのctor(存在する場合)は決して呼び出されません。よろしくお願いします。 – packoman

答えて

2

問題は、Visual Studioでデバッグしている間に実行されているWcfSvcHostによって引き起こされます。 thisによると、「WCFサービスホストは、WCFサービスプロジェクトでサービスを列挙し、プロジェクトの設定をロードし、それが見つかった各サービスのホストをインスタンス化します。ツールは、WCFサービステンプレートを通じてのVisual Studioに統合されたときに呼び出されますプロジェクトのデバッグを開始してください。

あなたはセルフホスティングしているので、WCFサービスホストを使用する必要はありませんので、あなたは、サービスを含むプロジェクトのプロジェクトプロパティページを通してそれを無効にすることができます。プロパティページに「WCFオプション」のタブが表示されます。その上で、 "デバッグ時にWCFサービスホストを開始..."オプションをオフにします。

+1

これは、そのトリックを行い、プログラムが開始されたときにツールバーの「面倒な」WcfHostService-PopUpを取り除いたものです。本当にありがとう! – packoman

関連する問題