2009-09-02 29 views
5

Tôi có dịch vụ WCF được lưu trữ bên trong Biểu mẫu Windows.WCF, Truy cập các điều khiển biểu mẫu cửa sổ từ một dịch vụ

Tôi làm cách nào để truy cập các điều khiển của biểu mẫu từ các phương pháp trong dịch vụ của tôi?

ví dụ tôi có

public interface IService { 
    [ServiceContract] 
    string PrintMessage(string message); 
} 

public class Service: IService  
{ 
    public string PrintMessage(string message) 
    { 
     //How do I access the forms controls from here? 
     FormTextBox.Text = message; 
    } 
} 

Trả lời

1

Sử dụng một đại biểu. Tạo một đại biểu trong codebehind của biểu mẫu của bạn tham chiếu đến một phương thức ghi vào hộp văn bản và chuyển nó tới Dịch vụ, sau đó dịch vụ có thể gọi đại biểu khi nó muốn in một thông báo.

Bạn sẽ gặp sự cố khi cố gắng cập nhật hộp văn bản vì đại biểu sẽ được gọi trên một chuỗi khác với chuỗi được tạo. Trong thế giới WPF, bạn sẽ sử dụng Dispatcher.BeginInvoke để giải quyết vấn đề này, không chắc chắn tương đương WinForms là gì.

+0

Điểm tốt về luồng. Điều này có thể là một nỗi đau :-) –

0

Dịch vụ sẽ cần tham chiếu đến cá thể của biểu mẫu chứ không chỉ là loại biểu mẫu.

Hơn nữa, bạn sẽ cần một cách để gửi giá trị cho các điều khiển biểu mẫu từ lớp dịch vụ của bạn. Điều này có thể được thực hiện bằng cách tự thực hiện các điều khiển hoặc được bảo vệ, hoặc bạn có thể tạo các thuộc tính trên lớp biểu mẫu của bạn để thiết lập các thuộc tính trên các điều khiển.

Một cách tiếp cận đơn giản sẽ là như sau:

  1. Thêm một constructor cho lớp dịch vụ của bạn mà phải mất một tham chiếu đến dụ mẫu của bạn. Nếu bạn đang lưu trữ dịch vụ của bạn bên trong các hình thức này nên được dễ dàng.
  2. Thêm thuộc tính công khai cho thuộc tính điều khiển bạn muốn đặt từ dịch vụ. Các thuộc tính phải công khai hoặc nội bộ và sẽ đặt giá trị của các thuộc tính điều khiển.
  3. Trong dịch vụ của bạn, bạn đặt giá trị của các thuộc tính mới được thêm vào.
3

Cách tốt nhất để xử lý trường hợp như vậy là đưa Biểu mẫu vào dịch vụ dưới dạng phụ thuộc. Tôi sẽ xác định một số loại giao diện mà tách riêng mã mẫu từ mã WCF:

public interface IFormService 
{ 
    string Text { get; set; } 
} 

Bạn có thể có mẫu của bạn thực hiện các giao diện IFormService bằng cách thiết lập thuộc tính thực sự bạn muốn cập nhật.

dịch vụ của bạn sẽ cần một thể hiện của IFormService để làm công việc của mình:

public class Service : IService 
{ 
    private readonly IFormService form; 

    public Service(IFormService form) 
    { 
     this.form = form 
    } 

    public string PrintMessage(string message) 
    { 
     this.form.Text = message; 
    } 
} 

Kể từ khi lớp dịch vụ hiện nay không có constructor mặc định, bạn cũng sẽ cần phải thực hiện một ServiceHostFactory tùy chỉnh mà có thể tạo ra các trường hợp của Dịch Vụ lớp và tiêm thực thi cụ thể của IFormService.

5

Trước hết, thuộc tính ServiceContract phải nằm trên giao diện chứ không phải phương thức PrintMessage().

Sử dụng phiên bản được sửa chữa của ví dụ của bạn, bạn có thể làm theo cách này.

[ServiceContract] 
public interface IService 
{ 
    [OperationContract] 
    string PrintMessage(string message); 
} 
public class Service : IService 
{ 
    public string PrintMessage(string message) 
    { 
     // Invoke the delegate here. 
     try { 
      UpdateTextDelegate handler = TextUpdater; 
      if (handler != null) 
      { 
       handler(this, new UpdateTextEventArgs(message)); 
      } 
     } catch { 
     } 
    } 
    public static UpdateTextDelegate TextUpdater { get; set; } 
} 

public delegate void UpdateTextDelegate(object sender, UpdateTextEventArgs e); 

public class UpdateTextEventArgs 
{ 
    public string Text { get; set; } 
    public UpdateTextEventArgs(string text) 
    { 
     Text = text; 
    } 
} 

public class MainForm : Form 
{ 
    public MainForm() 
    { 
     InitializeComponent(); 

     // Update the delegate of your service here. 
     Service.TextUpdater = ShowMessageBox; 

     // Create your WCF service here 
     ServiceHost myService = new ServiceHost(typeof(IService), uri); 
    } 
    // The ShowMessageBox() method has to match the signature of 
    // the UpdateTextDelegate delegate. 
    public void ShowMessageBox(object sender, UpdateTextEventArgs e) 
    { 
     // Use Invoke() to make sure the UI interaction happens 
     // on the UI thread...just in case this delegate is 
     // invoked on another thread. 
     Invoke((MethodInvoker) delegate { 
      MessageBox.Show(e.Text); 
     }); 
    } 
} 

Đây thực chất là giải pháp được đề xuất bởi @Simon Fox, tức là, sử dụng đại biểu. Điều này hy vọng chỉ cần đặt một số thịt trên xương, do đó, để nói chuyện.

+0

Điều đó có vẻ tốt Matt ngoại trừ dòng "service.TextUpdater = ShowMessageBox;" Khi tôi tạo dịch vụ của mình, tôi làm: ServiceHost myService = new ServiceHost (typeof (IService), uri); Vậy làm cách nào tôi có thể đặt thuộc tính TextUpdater nếu thuộc loại ServiceHost và không thuộc loại Dịch vụ? –

+0

Phải. Đặt thuộc tính TextUpdater thành thuộc tính tĩnh của lớp Service. Sau đó, dịch vụ của bạn sẽ có quyền truy cập vào đại biểu khi nó được khởi tạo. –

+0

Tôi đã cập nhật ví dụ về mã để rõ ràng hơn. –

0

Để hoàn chỉnh, có một cách tiếp cận đơn giản hơn bằng cách sử dụng cùng một giải pháp.

Bạn có thể trực tiếp gọi một đại biểu trên cùng một luồng bằng cách sử dụng phương thức gọi.

Invoke(new MethodInvoker(delegate{FormTextBox.Text = message;}); 
Các vấn đề liên quan