2013-12-09 3 views
2

Я пишу класс слушателя, который создает единственный HttpListener на случайном неиспользуемом порту и прослушивает его. Я попытался сделать это синглтон. Однако мне с трудом удерживать этот одноэлементный объект null при прослушивании случайному порту HTTP с ошибкой 10 раз.Элементы экземпляра одноэлементного объекта или статические члены класса

(.. Я показал, номер порта и HttpListener экземпляра в качестве членов одноплодной экземпляра Однако есть много других членов, которые я не показаны для простоты) Это мой код:

class Listener 
{ 
    private static Listener listener = null; //singleton instance 

    //member variables 
    private HttpListener httpListener = null; 
    private int port = -1; 

    static Listener() 
    { 
     listener = new Listener(); 
    } 

    private Listener() 
    { 
     try 
     { 
      port = //randomly generate 
      httpListener = new HttpListener(); 
      //start listening 
     } 
     catch(Exception ex) 
     { 
      //cant listen on randomly chosen port 
      listener = null; 
     httpListener = null; 
      port = -1; 
      return;    
     } 
    } 
} 

Однако внутри catch(), listener = null устанавливает listener на нуль только на время. Когда конструктор по умолчанию возвращает его, возвращается новый экземпляр Listener, поэтому listener внутри статического конструктора всегда имеет назначенный ему экземпляр . Таким образом, вместо listener = null внутри стандартного конструктор должен быть this = null, что является недопустимым.

Таким образом, я переместил весь код внутри статического конструктора. Но это forcesd меня

  • Либо делают члены экземпляра (port и httpListener) static или
  • или использовать listener.port, listener.httpListener везде

    класс Слушатель { частных статических Слушатель Слушатель = NULL; // одноточечно экземпляр

    //member variables 
    private HttpListener httpListener = null; 
    private int port = -1; 
    
    static Listener() 
    { 
        listener = new Listener(); 
    
    try 
        { 
        listener.port = //randomly generate 
         listener.httpListener = new HttpListener(); 
         //start listening 
        } 
        catch(Exception ex) 
        { 
         //cant listen on randomly chosen port 
        listener = null;  
         return;    
        } 
    } 
    
    private Listener() 
    { 
    } 
    

    }

Я не понимаю

Q1 ли сделать port & httpListenerstatic? (Это я несколько против принципов ООП) или

Q2 следует ли хранить их в качестве экземпляров и использовать listener. везде? (Это проблематично, поскольку в моем фактическом коде есть много таких членов и методов, и я должен приложить listener.)

Или я думаю, что все неправильно, и следовало бы по-другому?

+0

Вы пытаетесь взломать порт? – Fendy

+0

[почему одинокие люди злы] (http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx). Это действительно не похоже на то, что вы описываете, что вам нужен синглтон. – BartoszKP

+0

@BartoszKP ohkay ... что здесь не так? – Mahesha999

ответ

0

Как упоминает BartoszKP в комментариях, вы, вероятно, были бы лучше с заводским рисунком здесь.

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

public class ListenerFactory { 

    public IListener CreateListener(URI uri, int port) { 
     Listener l = new Listener(); 
     l.MessageReceived += OnMessageReceived; 
     // do whatever with l. loop until connection, or use l.Start() for instance 
     return l; 
    } 

    public static event EventHandler<MessageEventArgs> ListenerMessageReceived; 

    private static void OnMessageReceived(object sender, MessageEventArgs e) { 
     // trigger ListenerMessageReceived 
    } 
} 

public interface IListener { 
    event EventHandler<MessageEventArgs> MessageReceived; 
    void Send(byte[] data); 
} 

public class Listener : IListener { 
    // implement interface 
} 

Тогда вы просто позвоните new ListenerFactory().Create(host, port);, когда вам нужен новый слушатель, и если вы хотите слушать все сообщения, вы подписались на ListenerFactory.MessageReceived для входящих сообщений.

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


Вы должны переместить код инициализации httpListener на свой собственный метод, чтобы избежать воссоздания слушателя. Делая это и добавляя свойство для получения экземпляра слушателя, классы могут использовать Listener.Instance.Start() для повторного подключения, если статический конструктор не сможет подключиться.

public class Listener 
{ 
    private static Listener listener = null; //singleton instance 

    //member variables 
    private HttpListener httpListener = null; 
    private int port = -1; 

    static Listener() 
    { 
     listener = new Listener(); 
     // start listener 
     try { 
      listener.Start(); 
     } 
     catch { } 
    } 

    // Use this method in other classes to start listener if it fails 
    // in static constructor 
    public static Listener Instance { get { return listener; } } 

    private Listener() 
    { 
    } 

    public bool IsConnected { 
     get { return httpListener != null; } 
    } 

    public void Start() 
    { 
     if (IsConnected) { return; } 
     try 
     { 
      port = //randomly generate 
      httpListener = new HttpListener(); 
      //start listening 
     } 
     catch(Exception ex) 
     { 
      //cant listen on randomly chosen port 
     httpListener = null; 
      port = -1; 
      return;    
     } 
    } 
} 
+0

э-э, установите 'httpListener' в' null'. Должен ли я устанавливать 'listener' в' null'. Или просто, что мы никогда не должны ставить «статический» экземпляр на «null»? – Mahesha999

+0

Да, статический экземпляр никогда не установлен в null, вы только обновляете переменную экземпляра httpListener – Patrick

+0

Почему его плохая идея свести на нет «статический» singleton? – Mahesha999

1

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

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

class Listener 
{ 
    public static Listener listener = null; //singleton instance 

    //member variables 
    private HttpListener httpListener = null; 
    private int port = -1; 

    static Listener GetListener() 
    { 
     if (listener != null) 
     { 
      return listener; 
     } 

     try 
     { 
      listener = new Listener(); 
      listener.StartListening(); 
      return listener; 
     } 
     catch (Exception) 
     { 
      //cant listen on randomly chosen port 
      listener.Cleanup(); 
      listener = null; 
      throw; 
     } 
    } 

    private Listener() 
    { 
     port = RandomlyGenerate(); 
     httpListener = new HttpListener(); 
    } 

    private void StartListening() 
    { 
     //start listening 
    } 

    private void Cleanup() 
    { 
     httpListener.Close(); 
     httpListener = null; 
     port = -1; 
    } 
} 
+0

Так что это должно также содержать что-то 'static Listener getListener()', и мне нужно сделать 'Listener.getListener(). StartListening()'? – Mahesha999

+0

Yup. Я заменил статический конструктор статическим GetListener(), который лучше. Вышеприведенный код является иллюстративным, например, он не является потокобезопасным, GetListener() может попробовать прослушивать более одного порта, пока не найдет тот, который работает, и, вероятно, нет необходимости очищать HttpListener при каждой попытке. – StevieB

+0

Но как насчет сбрасывания «слушателя»? Или почему его плохая идея аннулировать «статический» синглтон? – Mahesha999

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