2016-04-24 8 views
0

Bär mit mir hier und versuchen, gehen Sie einfach auf schlechte Praxis :)C# Asynchron-Buchse über die Schnittstelle

Ich beginne das Konzept der Schnittstellen zu verstehen, und ich habe in meinem Programm implementiert .. Also ich werde versuchen, und erklären .. Ich erstelle eine Klassenbibliothek dll, die Schnittstelle mit meiner Alarmzentrale wird. Die Alarmzentrale kann zwei Arten von Verbindungen haben, IP und Serial. Also habe ich eine Schnittstelle namens IConnection implementiert.

eine Verbindung herzustellen, wie folgt:

//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(); 

in der konkreten Klasse (? Korrekte Terminologie) ich eine Methode implementieren namens Sendmessage, die ich Agnostiker nutzen zu Transport, die gut funktioniert.

Allerdings möchte ich nun einen asynchronen Handler hinzufügen, um Adhoc-Nachrichten zu verarbeiten, die nicht als Befehl/Antwort-Stil gesendet werden.

Ich habe einen Eventhandler in meinem Haupt TCPVerbindung Klasse arbeiten:

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.. 
    } 

aber ich abstrahieren will die IP-Sachen aus dem Verarbeitungscode und die process bis in meine Klasse, die die Schnittstelle verwendet bewegen zurück .. (ich weiß, dass ich das auch nicht erklären .. so lassen Sie mich wieder versuchen)

Ereignishandler in meinem Set up „Klasse TCPVerbindung: IConnection“

Schalten Sie Ereignis aus AlarmPanel Klasse Handling, die der Konstruktor wie folgt aussieht:

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

, die diese Schnittstelle (IConnection) verwendet, und haben die Möglichkeit, die Process Methode aus der alarmPanel Klasse, zu sagen, so dass ich dann die gleiche Methode für nennen kann, wenn ich die Serienereignisbehandlung Arbeits bekommen ..

+0

Sie verwenden mehrere Netzwerkschichten (7 Schichten). Sie haben eine Anwendungsschicht, die Nachrichten verarbeitet, und eine Transportschicht (seriell oder TCP). Ihre Nachrichten müssen den Nachrichtentyp enthalten, damit Ihre Anwendungsebene weiß, was mit den Nachrichten geschehen soll. Sie möchten also, dass alle Nachrichten als async behandelt werden, obwohl einige Master-Slaves und andere Ad-hoc-Nachrichten sind. Normalerweise sende ich alle Nachrichten mithilfe von Synchronisierungsmethoden. Ich würde anfangen, indem ich alle Nachrichtentypen definiere. Die Anwendungsschicht verfügt über eine Nachrichtenwarteschlange, in der die gesendeten Nachrichten mit der Antwort übereinstimmen und Adhoc übergeben wird. – jdweng

Antwort

1

Es klingt wie Sie ein Ereignis auf Ihrer Schnittstelle registrieren möchten, die AlarmPanel abonnieren kann. Auf diese Weise können Sie die Implementierung die Logik zum Abrufen der Nachricht behandeln lassen, aber lassen Sie AlarmPanel tun, was es mit der empfangenen Nachricht will.

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

Das klingt richtig und sieht aus wie die richtige Interpretation meines Posts, danke, ich werde es versuchen und Ihnen das Ergebnis mitteilen. –

+0

Cool. Lass es mich wissen, wenn ich irgendetwas klären kann. – smoksnes

+0

Ich habe es endlich geschafft, dies zu testen und es hat gut funktioniert, danke :) –

Verwandte Themen