2012-04-10 2 views
0

Я довольно новичок в программировании, поэтому несите меня, если мой вопрос недостаточно конкретный. Сейчас я пытаюсь сделать простой клиентский вход на моем сервере. Таким образом, приложение сервера знает, какие пользователи подключены. Когда клиент подключается, я хочу, чтобы на сервере запускалось событие, которое обновляет список пользователей. Но это не так, и я не могу понять, почему. Надеюсь, ты поможешь.Wpf Сервер/клиентский вход. Проблемы с событиями

В кодах я удалил, как пользователи должны отображаться в serverApp. Прямо сейчас мне просто нужно, чтобы мероприятие работало.

В моей библиотеке службы:

INetworkService контракта:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Runtime.Serialization; 
using System.ServiceModel; 
using System.Text; 

namespace NetworkLib 
{ 
    [ServiceContract] 
    public interface INetworkService 
    { 
     [OperationContract] 
     void Logon(UserInfo userInfo); 

     [OperationContract] 
     void Logout(); 
    } 
} 

NetworkService Класс:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Runtime.Serialization; 
using System.ServiceModel; 
using System.Text; 

namespace NetworkLib 
{ 
    public class NetworkService : INetworkService 
    { 
     public event EventHandler UserListChanged; 

     public void Logon(UserInfo userInfo) 
     { 
      OnUserListChanged(); 
     } 

     public void Logout() 
     { 
      OnUserListChanged(); 
     } 

     private void OnUserListChanged() 
     { 
      var handler = UserListChanged; 
      if (handler != null) 
      { 
       handler(this, EventArgs.Empty); 
      } 
     } 
    } 
} 

UserInfo Класс:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Runtime.Serialization; 

namespace NetworkLib 
{ 
    [DataContract] 
    public class UserInfo 
    { 
     [DataMember] 
     public string Name; 
    } 
} 

В моей ServerApp (WPF):

using System.ServiceModel; 
using NetworkLib; 

namespace ServerApp 
{ 
    public partial class MainWindow : Window 
    { 

     NetworkService networkService; 

     public MainWindow() 
     { 
      InitializeComponent(); 

      ServiceHost host = new ServiceHost(typeof(NetworkService)); 

      host.Open(); 

      networkService = new NetworkService(); 

      networkService.UserListChanged += networkService_UserListChanged; 

     } 

     private void networkService_UserListChanged(object sender, EventArgs e) 
     { 
      MessageBox.Show("It Works!"); 
     } 
    } 
} 

В моем ClientApp (WPF): (Сделал ссылку на службу к серверу)

namespace ClientApp 
{ 

    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, RoutedEventArgs e) 
     { 
      ServiceReference.NetworkServiceClient proxy = new ServiceReference.NetworkServiceClient(); 

      ServiceReference.UserInfo userInfo = new ServiceReference.UserInfo(); 

      userInfo.Name = "Test"; 

      proxy.Logon(userInfo); 

     } 
    } 
} 

ответ

2

При создании ServiceHost, вы должны предоставить NetworkService экземпляр вместо typeof(NetworkService)

ServiceHost host = new ServiceHost(networkService); 

Вы должны инициализировать его первый, конечно.

+0

С помощью того, что ilya.dorofeev сказал о создании одного экземпляра NetworkService [ServiceBehavior (InstanceContextMode = InstanceContextMode.Single)] и предоставить хосту этот экземпляр, как описано, он работает. Спасибо :) – user1077186

0

Я не смотреть в деталях но в целом ваш код выглядит нормально. Иногда в этой ситуации полезно запустить 2 экземпляра VisualStudio - один для сервера в отладке и один для клиента в отладке. Если вы поместите точку останова в клиентский код button1_Click в VS, который отлаживает клиент, а точка останова в NetworkServices.Logout в VS, которая отлаживает сервер, вы сможете перейти от кода клиента к серверу и легко увидеть, что происходит неправильно.

3

Вы подписываетесь на событие другого экземпляра NetworkService, чем экземпляр ServiceHost. В вашем случае каждый раз, когда вы делаете запрос на сервер, создается новый экземпляр NetworkService. Поместите следующий атрибут выше класса NetworkService:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] 

Тогда подписываться на событие:

var serviceInstance = (NetworkService)host.SingletonInstance; 
serviceInstance.UserListChanged += networkService_UserListChanged; 
+0

Спасибо большое. Используется: [ServiceBehavior (InstanceContextMode = InstanceContextMode.Single)], чтобы сделать его только одним экземпляром. Но когда я пытаюсь подписаться на событие, он бросает мне TargetInvocationException (InnerException: System.NullReferenceException Message = Ссылка на объект не установлена ​​в экземпляр объекта.) – user1077186

0

Почему вам нужна модель событий здесь? Почему бы просто не обрабатывать свое «событие» непосредственно в NetworkService.Logout(). Вызывает ли это отключение к событию, а затем связать это событие (которое, как верно указывает ilya.dofofeev, не на одном и том же объекте), дает какую-либо реальную выгоду?