2011-04-09 43 views
0

抱歉再次發佈相同的問題,但種類沒有得到正確的第一次。 :)在C#/ WCF中創建一個類的實例?

這是服務器應用程序的代碼,它可以接收連接並應將消息發送到客戶端。

正如你可以看到我有「Form1類:表格」爲GUI的東西,「類ServerWCallbackImpl:IServerWithCallback」與服務器的功能。

問題是,這些類不能通信,即我不能從窗體事件,如buttonClick引發服務器功能,我也不能改變窗體內的東西,比如TextBox1.Text + = ... ,從服務器功能。

也許有人可以請解釋一下,代碼應該怎麼樣,以便它能工作?

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.ServiceModel; 

namespace server 
{ 


[ServiceContract(Namespace = "server", CallbackContract = typeof(IDataOutputCallback), SessionMode = SessionMode.Required)] 


public interface IServerWithCallback   ///// what comes from the client to the server. 
{ 
    [OperationContract(IsOneWay = true)] 
    void StartConnection(string clientName); 

    [OperationContract(IsOneWay = true)] 
    void Message_Cleint2Server(string msg); 
} 


public interface IDataOutputCallback   ///// what goes from the sertver, to the client. 
{ 
    [OperationContract(IsOneWay = true)] 
    void AcceptConnection(); 

    [OperationContract(IsOneWay = true)] 
    void Message_Server2Client(string msg); 
} 


    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 


     private void Form1_Load(object sender, EventArgs e)  /// once the form loads, create and open a new ServiceEndpoint. 
     { 
       ServiceHost duplex = new ServiceHost(typeof(ServerWCallbackImpl)); 
       duplex.AddServiceEndpoint(typeof(IServerWithCallback), new NetTcpBinding(), "net.tcp://localhost:9080/service"); 
       duplex.Open(); 
       this.Text = "SERVER *on-line*"; 
     } 

     private void buttonSendMsg_Click(object sender, EventArgs e) 
     { 
      /// callback.Message_Server2Client(textBox2.Text); 
      /// The name 'Message_Server2Client' does not exist in the current context :(
     } 

    } 



     class ServerWCallbackImpl : IServerWithCallback /// NEED TO SOMEHOW MERGE THIS ONE WITH THE FORM1 CLASS 
     { 


      IDataOutputCallback callback = OperationContext.Current.GetCallbackChannel<IDataOutputCallback>(); 


      public void StartConnection(string name) 
      { 
       /// TextBox1.text += name + " has connected!"; 
       /// 'TextBox1' does not exist in the current context :(
       /// can't reach form1 components. :/ 
       MessageBox.Show(name + " has connected!"); 
       Message2Client("Welcome, "+name+"!"); 
      } 


      public void Message_Cleint2Server(string msg) 
      { 
       /// TextBox1.text += msg; 
       /// 'TextBox1' does not exist in the current context :(
       /// can't reach form1 components. :/ 
      } 


      public void Message2Client(string msg) 
      { 
       callback.Message_Server2Client(msg); 
      } 


     } 

} 

回答

1

雙工變量的生存期僅限於Form1_Load方法。這意味着您的主機將在方法結束時終止。爲了保持主機運行,在方法外聲明雙工變量,並在方法中實例化它。

像這樣:

public partial class Form1 : Form { 
    //Declare the variable in the class, not the method body 
    private ServiceHost duplex; 

    public Form1() { 
     InitializeComponent(); 
    } 

    // once the form loads open a new ServiceEndpoint. 
    private void Form1_Load(object sender, EventArgs e) { 
      duplex = new ServiceHost(typeof(ServerWCallbackImpl)); 
      duplex.AddServiceEndpoint(typeof(IServerWithCallback), new NetTcpBinding(), "net.tcp://localhost:9080/service"); 
      duplex.Open(); 
      this.Text = "SERVER *on-line*"; 
    } 

    private void buttonSendMsg_Click(object sender, EventArgs e) { 
     /// callback.Message_Server2Client(textBox2.Text); 
     /// The name 'Message_Server2Client' does not exist in the current context :(
    } 

} 

EDIT1:

如果ServiceHost的是在您的示例實例化一個類型一樣,類型的實例會爲每個連接創建。您可以將實例的生命週期設置爲會話,呼叫或連接,我相信。我不確定該對象如何訪問您的表單。但是,如果您自己實例化ServerWCallbackImpl類並將引用傳遞給將使用該實例的主機。

public partial class Form1 : Form { 
    //Declare the variable in the class, not the method body 
    private ServiceHost duplex; 
    private ServerWithCallbackImpl localInstance; 

    public Form1() { 
     InitializeComponent(); 
    } 

    private void Form1_Load(object sender, EventArgs e) { 
     localInstance = new ServerWithCallbackImpl(); 
     NetTcpBinding binding = new NetTcpBinding(); 
     duplex = new ServiceHost(localInstance, new Uri[] { new Uri("net.tcp://localhost:9080") }); 
     duplex .AddServiceEndpoint(typeof(IServerWithCallback), binding, "service"); 
     duplex .Open(); 
     this.Text = "SERVER *on-line*"; 
    } 
} 

ServerWithCallbackImpl對象將不得不跟蹤它的客戶端。要使服務器更新GUI,您可能需要將對Form的參考引用傳遞給ServerWithCallbackImpl構造函數。看看the Publish/Subscriber pattern以更深入地瞭解回調。

+0

感謝您的提示!也許還有關於如何從表單事件(例如buttonClick)引發服務器功能或者在表單中更改某些內容(例如TextBox1.Text + = ...)的任何想法? – Roger 2011-04-09 12:59:44

+0

我用附加信息編輯了答案:) – Farawin 2011-04-13 08:11:51