c # использование одного и того же экземпляра класса между двумя формами для TCP - PullRequest
1 голос
/ 04 ноября 2011

Хорошо, я полностью застрял. Мои навыки поиска отсутствуют, и я не могу найти ничего, что заставляет меня видеть, что мне нужно делать.

У меня есть приложение Telnet. Form1 соединяет и преформирует сокет через класс. Класс указан в первой форме, например:

//form1
telnet tc;

private void connect_Click(object sender, EventArgs e)
{
  tc = new telnet (IP, Port);
}

То, что я пытаюсь сделать, это использовать этот же метод в form2. form2 является окном конфигурации и требует получения данных с сервера telnet для сохранения в файл XML. через

 //form 1
 tc.read();

Я мог бы вызвать новый экземпляр класса telnet, но это было бы пустой тратой ресурсов, и я думаю, что есть лучший способ его кодировать.

Так что я хотел бы знать, находясь в форме2. Как сообщить событие нажатия кнопки для доступа к tc из form1?

До сих пор я не смог выяснить, как получить ссылку на form1 tc или кнопку connect_click на форму 2.

 //form2
 private void read_click(object sender, EventArgs e)
 {
   tc.read();  // how do i call it? or even call a method of form 1 to button click?
   ... write data from tc.read()
  }

Ответы [ 4 ]

2 голосов
/ 04 ноября 2011

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

Не создавайте экземпляры класса telnet в любой форме. Используйте Dependency Injection вместо . Создайте экземпляр Telnet на верхнем уровне приложения и передайте его обеим формам.

Это поможет вам разделить проблемы в вашем приложении и упростит проведение модульного тестирования вашего приложения в будущем (потому что вы можете создать для них подделку Telnet).

Что-то вроде:

public static void Main(string[] args)
{
    // maybe get these from the command line, or from app.config
    const string ipAddress = "10.0.0.1";
    const string port = "80";

    var telnet = new Telnet(ipAddress, port);

    var mainForm = new MainForm(telnet);
    mainForm.ShowDialog();
}

// ...

public class MainForm : Form
{
    private Telnet telnet;

    public MainForm(Telnet telnet)
    {
        this.telnet = telnet;
    }

    // Todo: Use telnet in other methods

    private void ShowSubForm()
    {
        var subForm = new SubForm(telnet);
        subForm.Show();
    }
}

Это лучше, чем Singleton или статический экземпляр, потому что он позволит вам легче менять свое приложение в будущем, он позволит вам повторно использовать ваш класс Telnet в будущем, не будет ограничивать вас только иметь один Telnet экземпляр на программу, и вам будет намного легче писать модульные тесты для вашего кода, когда вы дойдете до этой точки.

Если вам необходимо получить информацию о том, какой IP-адрес и порт следует использовать из главной формы, используйте Factory Pattern , создайте фабрику в Main и передайте ее в форму. Затем вызовите фабрику в конструкторе MainForm:

public class TelnetFactory
{
    public Telnet Create(string ipAddress, string portNumber)
    {
        return new Telnet(ipAddress, portNumber);
    }
}

// ...

public class MainForm : Form
{
    private TelnetFactory telnetFactory;
    private Telnet telnet;

    public MainForm(TelnetFactory telnetFactory)
    {
        this.telnetFactory = telnetFactory;
    }

    // Called by a UI action of some sort...
    private void Connect(string ipAddress, string portNumber)
    {
        if(this.telnet != null)
        {
            this.telnet = telnetFactory.Create(ipAddress, portNumber);
        }
    }

    // Todo: Use telnet in other methods

    // Todo: Just pass the existing telnet instance to SubForm
}

Если вы создаете обе формы в третьем промежуточном классе, вместо создания одной формы из другой формы вы все равно можете использовать эти шаблоны. Просто создайте экземпляр Telnet в этом промежуточном классе или передайте фабрику этому промежуточному классу.

0 голосов
/ 04 ноября 2011

Почему бы не поместить код из формы один в его собственный метод и объявить этот метод как открытый статический, как этот.

public static void connect()
{
  tc = new telnet (IP, Port);
}
0 голосов
/ 04 ноября 2011

обновление на основе комментария bryanmac.Я предлагал статический метод, чтобы быстро что-то сделать.вот более подходящая, не синглтонная, реализация (на основе кода Брайана)

public static class Communicator
{
    private static Communicator _instance;
    private Communicator() {}

    public static Telnet Telnet 
    { 
      get
      {
         if (_instance == null) 
         { 
            throw new InvalidOperationException("No telnet session established"); 
         }

         return _instance;
      }
    }

     public static void OpenSession(string ip, int port)
     {
         _instance = new telnet(ip, port);
     }
}

// form1
private void connect_Click(object sender, EventArgs e)
{
  Communicator.OpenSession(IP, Port);
}

//form2
 private void read_click(object sender, EventArgs e)
 {
   Communicator.Telnet.Read();
  }
0 голосов
/ 04 ноября 2011

Один из вариантов - создать одноэлементный объект, который владеет связью.

http://msdn.microsoft.com/en-us/library/ff650316.aspx

Итак, если у вас было что-то вроде:

public class Communicator
{
    Telnet m_telnet;

    private static Communicator instance;

    private Communicator() {m_telnet = new Telnet()}

    public static Communicator Instance
    {
        get {
            if (instance == null) {
                instance = new Communicator();
         }
         return instance;
     }

     public string DoSomething()
     {
         return m_telnet.DoSomething();
     }
   }
}

Тогда в ваших функциях формы вы можете просто:

Communicator.Instance.DoSomething();

Так как различные формы обращаются к этому объекту, не должно быть потокобезопасным. Если это так, то вы можете использовать шаблон двойной блокировки.

...