Справка дизайна – полиморфная обработка событий

Попробуйте это:

RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteRule ^(.*)$ %{HTTP_HOST}$1 [C]
RewriteRule ^www\.(.*)$ http://$1 [L,R=301]

, Если хост запускается с www, мы засовываем большое количество на запуск URL, затем снимаем "www".

5
задан SwDevMan81 7 May 2013 в 18:00
поделиться

5 ответов

Я мог бы сделать MyEvent1Args и MyEvent2Args производными от общего базового класса и сделать следующее:

public class BaseEventArgs : EventArgs
{
    public byte[] Data;
}

public class MyEvent1Args : BaseEventArgs
{ … }
public class MyEvent2Args : BaseEventArgs
{ … }


public delegate void TestHandlerWithInheritance(BaseEventArgs baseEventArgs);

public event TestHandlerWithInheritance mTestHandler;

mTestHandler += new TestHandlerWithInheritance(TestHandlerForEvent1Args);
mTestHandler += new TestHandlerWithInheritance(TestHandlerForEvent2Args);

    void TestHandlerForEvent1Args(BaseEventArgs baseEventArgs)
    {
        MyEvent1Args my_event1_args = (baseEventArgs as MyEvent1Args);
        if (my_event1_args != null)
        {
            // Do stuff here
            Sub1Enums mid = my_event1_args.MessageID;
            byte[] data = my_event1_args.Data;
        }
    }

    void TestHandlerForEvent2Args(BaseEventArgs baseEventArgs)
    {
        MyEvent2Args my_event2_args = (baseEventArgs as MyEvent2Args);
        if (my_event2_args != null)
        {
            // Do stuff here
            Sub2Enums mid = my_event2_args.MessageID;
            byte[] data = my_event2_args.Data;
        }
    }

А в алгоритме синтаксического анализа у меня есть что-то вроде этого в зависимости от того, какое это сообщение:

        if (mTestHandler!= null)
        {
            mTestHandler (new MyEvent1Args(Sub1Enums.ID1, new byte[] { 0x01 }));
        }
        if (mTestHandler!= null)
        {
            mTestHandler (new MyEvent2Args(Sub2Enums.ID2, new byte[] { 0x02 }));
        }
1
ответ дан 14 December 2019 в 13:44
поделиться

Если вы пытаетесь уменьшить количество обработчиков событий, чтобы абстрагироваться / упростить кодирование вы должны это сделать, тогда применение шаблона проектирования Double Dispatch к вашим аргументам событий было бы идеальным. По сути, это элегантное (но многословное) исправление необходимости выполнять безопасное приведение типов (/ - это проверка instanceof)

3
ответ дан 14 December 2019 в 13:44
поделиться

Отвлекитесь от полиморфизма и изучите использование косвенного обращения, в частности, шаблон агрегатора событий, если вы еще этого не сделали; Сначала Фаулер @ http://martinfowler.com/eaaDev/EventAggregator.html , а затем сообщения Джереми Миллера, если вам нужно больше идей.

Ура,
Беррил

1
ответ дан 14 December 2019 в 13:44
поделиться

Вы можете рассмотреть несколько вариантов (я не уверен, чего именно вы хотите здесь достичь):

1. Создайте иерархию EventArgs и возложите на наблюдателей ответственность за фильтрацию того, что им интересно (это то, что вы предложили в своем ответе). Это особенно важно, если некоторых наблюдателей интересуют несколько типов сообщений, в идеале описываемых типом базового класса.

2. Не используйте делегаты .Net, просто реализуйте его самостоятельно, чтобы при регистрации делегата он также принимал ожидаемый тип события. Предполагается, что вы выполнили работу из (1), но хотите передать фильтрацию вашему классу, а не наблюдателям

Например (непроверено):

enum MessageType
{
Type1,Type2
}
private Dictionary<MessageType, TestHandlerWithInheritance> handlers;
public void RegisterObserver(MessageType type, TestHandlerWithInheritance handler)
{
  if(!handlers.ContainsKey(type))
  {
    handlers[key] = handler;
  }
  else
  {
    handlers[key] = Delegate.Combine(handlers[key] , handler);
  }
}

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

3. Реализуйте события так, как это делается в WinForms, чтобы у вас не было базового события для когда-либо выставленного события. Это имеет смысл, если вы ожидаете, что событий будет больше, чем наблюдателей.

Например:

public event EventHandler SthEvent
{
    add
    {
        base.Events.AddHandler(EVENT_STH, value);
    }
    remove
    {
        base.Events.RemoveHandler(EVENT_STH, value);
    }
}

public void AddHandler(object key, Delegate value)
{
    ListEntry entry = this.Find(key);
    if (entry != null)
    {
        entry.handler = Delegate.Combine(entry.handler, value);
    }
    else
    {
        this.head = new ListEntry(key, value, this.head);
    }
}


public void RemoveHandler(object key, Delegate value)
{
    ListEntry entry = this.Find(key);
    if (entry != null)
    {
        entry.handler = Delegate.Remove(entry.handler, value);
    }
}


private ListEntry Find(object key)
{
    ListEntry head = this.head;
    while (head != null)
    {
        if (head.key == key)
        {
            return head;
        }
        head = head.next;
    }
    return head;
}

private sealed class ListEntry
{
    // Fields
    internal Delegate handler;
    internal object key;
    internal EventHandlerList.ListEntry next;

    // Methods
    public ListEntry(object key, Delegate handler, EventHandlerList.ListEntry next)
    {
        this.next = next;
        this.key = key;
        this.handler = handler;
    }
}

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

1
ответ дан 14 December 2019 в 13:44
поделиться

Если вы пытаетесь уменьшить количество обработчиков событий для экономии ОЗУ, сделайте то, что делает Microsoft (в System.ComponentModel.Component), и используйте EventHandlerList для отслеживания все ваши мероприятия. Вот статья, в которой описывается сохранение использования памяти с помощью EventHandlerList , а - аналогичная статья, написанная на C #. .

Суть в том, что вы можете объявить single EventHandlerList (не забудьте удалить его) в своем классе вместе с уникальным ключом:

public class Foo
{
    protected EventHandlerList listEventDelegates = new EventHandlerList();
    static readonly object mouseDownEventKey = new object();

... переопределить свойство события:

public event MouseEventHandler MouseDown {  
   add { listEventDelegates.AddHandler(mouseDownEventKey, value); }
   remove { listEventDelegates.RemoveHandler(mouseDownEventKey, value); }
}

... и предоставить метод RaiseEvent:

protected void RaiseMouseDownEvent(MouseEventArgs e)
{
    MouseEventHandler handler = (MouseEventHandler) base.Events[mouseDownEventKey];
    if (handler != null)
    {
        handler(this, e);
    }
}

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

0
ответ дан 14 December 2019 в 13:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: