2016-04-24 2 views
0

медведя со мной здесь и попытаться идти легко на плохой практике :)C# асинхронного гнездо через интерфейс

Я начинаю понимать концепцию интерфейсов и я реализовал один в моей программе .. Так что я буду стараться и объясните .. Я создаю DLL библиотеки классов, которые будут взаимодействовать с моей панелью тревоги. Панель сигнализации может иметь два типа соединения: IP и Serial. Поэтому я реализовал интерфейс для этого, называемого IConnection.

и создать соединение следующим образом:

//IConnection connection = new SerialConnection("com1", 9600); 
IConnection conn = new TcpConnection(System.Net.IPAddress.Parse("192.168.0.14"), 1234); 

AlarmPanel alarm = new AlarmPanel(conn, Pass); 
alarm.SetLogger(logger); 
alarm.Connect(); 

в конкретном классе (? Правильной терминологии) я реализую метод, называемый SendMessage, который я использую, чтобы быть агностиком транспорт, который работает хорошо.

Однако теперь я хочу добавить обработчик async для обработки сообщений adhoc, отправленных обратно, которые не являются сообщениями стиля командной строки/ответа.

У меня есть EventHandler, работающий в моей основной TCPConnection Класс:

private static void tcpReceive(Socket client) 
    { 
     try 
     { 
      // Create the state object. 
      StateObject state = new StateObject {workSocket = client}; 

      // Begin receiving the data from the remote device. 
      client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, 
       new AsyncCallback(receiveCallback), state); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
    } 

    private static void receiveCallback(IAsyncResult ar) 
    { 
     try 
     { 
      StateObject state = (StateObject)ar.AsyncState; 
      Socket client = state.workSocket; 

      // Read data from the remote device. 
      int bytesRead = client.EndReceive(ar); 

      if (bytesRead <= 0) return; // No data... 

      // Console.WriteLine("Ascii {0}", Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); 
      Console.WriteLine("Raw: {0}", BitConverter.ToString(state.buffer, 0, bytesRead)); 

      processMessage(new Response {Data = state.buffer,BytesLength = bytesRead}); 

      client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(receiveCallback), state); 

     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
    } 

    private static void processMessage(Response resp) 
    { 
     // Do something with the message here.. 
    } 

Однако я хочу, чтобы абстрагировать IP материал из кода обработки и перемещения ProcessMessage обратно в мой класс, который использует интерфейс .. (Я знаю, что я не объяснить это хорошо .. поэтому позвольте мне еще раз попробовать)

Настройка обработчика событий в моей «класс TCPConnection: IConnection»

Включите обработку от AlarmPanel класса, который конструктор выглядит как событие:

public AlarmPanel(IConnection connection, int Password) 
    { 
     _connection = connection; 
     _Password = Password; 
    } 

, который использует этот интерфейс (IConnection), и быть в состоянии сказать, использовать метод ProcessMessage от alarmPanel класса, так что я могу затем вызвать тот же метод, когда я получаю серийные обработки событий работать ..

+0

Вы используете несколько слоев сети (7 слоев). У вас есть сообщения для обработки прикладного уровня и транспортный уровень (последовательный или TCP). Ваши сообщения должны содержать тип сообщения, чтобы ваш уровень приложения знал, что делать с сообщениями. Поэтому вы хотите, чтобы все получаемые сообщения обрабатывались как асинхронные, хотя некоторые из них являются подчиненными и другими adhoc. Обычно я отправляю все сообщения, используя методы синхронизации. Я бы начал с определения всех типов сообщений. Уровень приложения будет иметь очередь сообщений, в которой сообщения отправки будут сопоставляться с ответом и позволят adhoc пройти. – jdweng

ответ

1

Похоже, что вы хотите зарегистрировать событие на своем интерфейсе IConnection, на который могут подписаться AlarmPanel. Таким образом, вы можете позволить реализации IConnection обрабатывать логику для получения сообщения, но пусть AlarmPanel делает то, что хочет, с полученным сообщением.

public class AlarmPanel 
{ 
    public AlarmPanel(IConnection connection, int Password) 
    { 
     _connection = connection; 
     _Password = Password; 
     // Bind event. 
     _connection.MessageReceived += ProcessMessage; 
    } 

    private void ProcessMessage(object sender, MessageEventArgs e) 
    { 
     // Do your central processing here with e.Message. 
    } 
} 

public interface IConnection 
{ 
    event Action<object, MessageEventArgs> MessageRecieved; 
} 

public class TcpConnection : IConnection 
{ 
    // Other code. 

    private static void processMessage(Response resp) 
    { 
     // Do something with the message here.. 
     var eventArgs = new MessageEventArgs 
     { 
      Message = response 
     }; 
     OnMessageReceived(eventArgs); 
    } 

    protected virtual void OnMessageReceived(MessageEventArgs e) 
    { 
     // Call subscribers. 
     var handler = MessageRecieved; 
     if (handler != null) handler(this, e); 
    } 
    public event Action<object, MessageEventArgs> MessageRecieved; 
} 

// Class for passing Response back to AlarmPanel. 
public class MessageEventArgs : System.EventArgs 
{ 
    Response Message { get; set; } // Consider using an interface for Response. 
} 
+0

Это звучит правильно и выглядит как правильная интерпретация моего поста, спасибо, я попробую это и дам вам знать результат. –

+0

Прохладный. Дай мне знать, если я смогу прояснить ситуацию. – smoksnes

+0

Я, наконец, добрался до тестирования этого, и он отлично работал, спасибо :) –

Смежные вопросы