Наблюдатели в ASP.Net с делегатами - PullRequest
1 голос
/ 19 августа 2011

Ну, я работаю на сайте asp.net 3.5.

Я установил Наблюдателя так:

public delegate void ActionNotification();

protected Dictionary<string, List<ActionNotification>> Observers
{
    get
    {
        Dictionary<string, List<ActionNotification>> _observers = Session["Observers"] as Dictionary<string, List<ActionNotification>>;
        if (_observers == null)
        {
            _observers = new Dictionary<string, List<ActionNotification>>();
            Observers = _observers;
        }
        return _observers;
    }
    set
    {
        Session["Observers"] = value;
    }
}

public void Attach(string actionName, ActionNotification observer)
{
    if (!Observers.ContainsKey(actionName))
    {
        Observers.Add(actionName, new List<ActionNotification>());
    }
    Observers[actionName].Add(observer);
}

public void Detach(string actionName, ActionNotification observer)
{
    if (Observers.ContainsKey(actionName))
    {
        Observers[actionName].Remove(observer);
    }

}
public void DetachAll(string actionName)
{
    if (Observers.ContainsKey(actionName))
    {
        Observers.Remove(actionName);
    }
}

public void Notify(string action)
{
    if (Observers.ContainsKey(action))
    {
        foreach (ActionNotification o in Observers[action])
        {
            o.Invoke();
        }
    }
}

Я использую наблюдателя так:

//Esta es llamada al notify con cierto action       
protected void btnNext_Click(object sender, ImageClickEventArgs e)          
{           
    Notify("Next");         
} 
//Y este es el register del Listener            
Attach("Next", new ActionNotification(NextButton_Click)); 

Если до o.Invoke(); Например, я изменяю заголовок страницы на «Привет». А внутри "NextButton_Click" я установил его на "Goodbye", после окончания NextButton_Click заголовок возвращается к "Hello" ...

Есть идеи, почему?

1 Ответ

2 голосов
/ 19 августа 2011

Мне кажется, проблема в том, что «Страница» в вашем событии NextButton_Click не совпадает со страницей, на которой вы установили заголовок «Привет».Поскольку вы передаете события в сеансе, когда событие вызывается, объект, на который он действует, больше не находится в области видимости.Вы можете воссоздать его с помощью следующего кода (который использует EventHandlers, но они в основном совпадают с тем, что вы обрисовали в своем коде)

protected void Page_Load(object sender, EventArgs e)
{
    this.Page.Title = "test";

    //Store it in your session...seems like a weird thing to do given how your page should be stateless, so I would think about what you are
    //trying to do a bit more carefully.  You don't want to call an event handler such as test below from another page in your asp.net app.
    Dictionary<string, EventHandler> myEvents = null;
    if (Session["Invokers"] == null)
    {
        myEvents = new Dictionary<string, EventHandler>();
        Session["Invokers"] = myEvents;
    }
    else
    {
        myEvents = Session["Invokers"] as Dictionary<string, EventHandler>;
    }
    //If the event handler key is not in there then add it
    if (myEvents.ContainsKey("buttonClickOnPageDefault") == false)
    {
        //Subscribe to event (i.e. add your method to the invokation list
        this.TestEvent += new EventHandler(test);
        myEvents.Add("buttonClickOnPageDefault", this.TestEvent);
    }
    else
    {
        //if it does contain this key then you may already be subscribed to event, so unsubscribe in case and then resubscribe...you could
        //probably do this more elegantly by looking at the vales in the GetInvokationList method on the eventHandler
        //Wire up the event
        this.TestEvent -= new EventHandler(test);
        this.TestEvent += new EventHandler(test);
    }
    //Resave the dictionary.
    Session["Invokers"] = myEvents;
}

void test(object o, EventArgs e)
{
    this.Page.Title = "testEvent";
}

public event EventHandler TestEvent;

protected void Button1_Click(object sender, EventArgs e)
{
    if (Session["Invokers"] != null)
    {
        Dictionary<string, EventHandler> myEvents = (Dictionary<string, EventHandler>)Session["Invokers"];
        if (myEvents.ContainsKey("buttonClickOnPageDefault"))
        {
            EventHandler ev = myEvents["buttonClickOnPageDefault"];
            ev(null, EventArgs.Empty);
        }
    }
}

Если вы поместите вышеуказанный код на страницу asp.netон никогда не изменит заголовок страницы, но если вы установите точку останова в методе Test, вы увидите, что она попадет.Причина в том, что он попадает на другую страницу (и эта страница выходит за рамки видимости и может не собирать мусор, поскольку ваше событие все еще имеет ссылку на него, так что это может вызвать утечку памяти ... будьте осторожны с этим!).На самом деле, вы, вероятно, не должны использовать свои события таким образом (по крайней мере, чтобы не действовать на странице ... возможно, у нее есть какая-то утилита для доменных объектов).Обратите внимание, что следующее будет работать (как его действие на той же странице)

protected void Page_Load(object sender, EventArgs e)
{
    this.Page.Title = "test";

    //Store it in your session...seems like a weird thing to do given how your page should be stateless, so I would think about what you are
    //trying to do a bit more carefully.  You don't want to call an event handler such as test below from another page in your asp.net app.
    this.TestEvent += new EventHandler(test);
    Session["Invoker"] = this.TestEvent;
}

void test(object o, EventArgs e)
{
    this.Page.Title = "testEvent";
}

public event EventHandler TestEvent;

protected void Button1_Click(object sender, EventArgs e)
{
    if (Session["Invoker"] != null)
    {
        EventHandler ev = (EventHandler)Session["Invoker"];
        ev(null, EventArgs.Empty);
    }
}

Надеюсь, что это даст вам несколько советов, где ваша проблема может быть.

...