Попытка создать метод, который может записывать в приложение консоли или формы - PullRequest
2 голосов
/ 31 мая 2011

Я работаю на общем сервере и клиентских программах.Проблема, с которой я сталкиваюсь, заключается в том, что когда я нахожусь в OnDataReceived на моем клиенте и сервере, я не знаю, что делать с данными.В идеале он должен выводить полученные данные в окно, но я не знаю, будет ли это приложение Form или Console.Поэтому вопрос в том, как мне создать общий метод, который может обрабатывать оба, или, если это невозможно, что мне делать вместо этого?

Код, с которым я работаю:

            SocketPacket theSockId = (SocketPacket)asyn.AsyncState;

            int iRx = theSockId.m_currentSocket.EndReceive(asyn);
            char[] chars = new char[iRx + 1];
            Decoder decode = Encoding.Default.GetDecoder();
            int charLength = decode.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
            String szData = new String(chars);

            //Handle Message here

            WaitForData();

И сокет класса пакета:

    class SocketPacket
    {
     public Socket m_currentSocket;
     public byte[] dataBuffer = new byte[1024];//Buffer to store the data by the client

     public SocketPacket(Socket socket)
     {
        m_currentSocket = socket;
     }
    }

PS.Я не знаю, нужно ли это знать, но я делаю асинхронный клиент / сервер.

Ответы [ 5 ]

3 голосов
/ 31 мая 2011

Ваши классы общения не должны заботиться о том, что происходит с данными, которые они получают.Вместо этого они должны либо сделать данные доступными для класса, который этого хочет.Один из способов сделать это - предоставить метод getData (), который получал данные и затем возвращал их вызывающей стороне.Еще лучше было бы предоставить событие DataArrived, которое вызывалось всякий раз, когда вы получали данные.Таким образом, любое количество потребителей может прослушивать данные, но ваш код связи не должен знать, какие классы слушают или что они планируют делать с данными.

РЕДАКТИРОВАТЬ :

Простой пример:

public class MyClassWithEvent
{
    public delegate void DataArrivedDelegate(string data);
    public event DataArrivedDelegate DataArrived;

    public void GetSomeData()
    {
        // Communication code goes here; stringData has the data

        DataArrivedDelegate handler = DataArrived;
        if (handler != null)
        {
            // If you want to raise the event on this thread, this is fine
            handler(stringData);
        }
    }
}

В вашем классе слушателя:

public MyListener
{

    public MyListener(MyServer server)
    {
        // Sets MyListenerMethod to be called when DataArrived is raised
        server.DataArrived += MyListenerMethod;
    }

    public void MyListenerMethod(string data)
    {
        // Do something with the data
        Console.WriteLine(data);
    }
}
2 голосов
/ 31 мая 2011

Запустить событие со строкой?Я бы помог, если бы строка буфера данных была членом объекта сокета - тогда вы могли бы запустить событие, используя только объект сокета и ваш обработчик событий, каким бы он ни был, имел бы все, что ему могло понадобиться, чтобы решить, чтоделать с данными.

Ргдс, Мартин

1 голос
/ 31 мая 2011

Вы можете попытаться реализовать стратегию

interface IOutputStrategy
{
    void Output(string message);
}

class ConsoleOutput:IOutputStrategy
{
    public void Output(string message)
    {
        Console.Writeline(message);
    }
}

class FormOutput:IOutputStrategy
{
    public void Output(string message)
    {
        // output where you want
    }
}

и на сервере / клиенте вы будете иметь тип IOutputStrategy

//Server
IOutputStrategy instance = new ConsoleOutput();

//Client
IOutputStrategy instance = new FormOutput();

А затем в обратном вызове OnDataReceived вы можете использовать текущий IOutputStrategyэкземпляр для вывода сообщения

instance.Output(szData);

Надеюсь, это поможет

1 голос
/ 31 мая 2011

Я бы создал интерфейс, где я мог бы написать информацию о событии, что-то вроде IEventSink.Поэтому OnDataReceived работает с экземпляром IEventSink и вызывает для него метод Write.Тогда у меня будет 2 реализации интерфейса: одна, которая пишет на консоли, и одна, которая пишет на форме.

0 голосов
/ 31 мая 2011

Это хорошее место для внедрения зависимостей.

  1. Создайте интерфейс (пока будем называть его ISiemsen), который имеет строковое свойство с именем «ShowTheResult»
  2. Теперь, в любом объекте, который вы хотите иметь возможность показать результат (форма, консольное приложение, веб-форма ...), вы реализуете интерфейс ISiemsen
  3. Внутри свойства, установленного для «ShowTheResult», вы присваиваете значение тому, что удовлетворяет потребность в этом объекте. (Если это консоль, вы выполняете console.WriteLine (value), если это форма, вы присваиваете значение текстовому полю)
  4. Измените ваш рабочий процесс так, чтобы он принимал ссылку на вашу рабочую функцию и позволял ему отправлять ответ в любое время.

    protected void getResults(ISiemsen siemens ... ) 
     {
       SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
       int iRx = theSockId.m_currentSocket.EndReceive(asyn);
       char[] chars = new char[iRx + 1];
       Decoder decode = Encoding.Default.GetDecoder();
       int charLength = decode.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
       String szData = new String(chars);
    
    
       WaitForData();
    //Handle Message here
       siemsen.ShowTheResult(theResult);
     }
    

Используя эту технику, элемент пользовательского интерфейса не знает и не заботится о том, откуда поступают данные, а рабочий процесс не знает и не заботится о том, куда он идет ... он «слабо связан».

...