0

I'm creating web application, using ASP.NET MVC4 and SignalR. I've tried to create repository for some Game class. Also, I want to fire event everytime item is added.

C#

public class Repository : Dictionary<string, Game>
{
    private static Repository _instance;

    public delegate void AddItemEventHandler(object sender, EventArgs e);
    private AddItemEventHandler handler;

    public event AddItemEventHandler OnAddItem
    {
        add 
        {
            if(handler != null)
            {
                handler -= value;
            }                
            handler += value;
        }
        remove 
        {
            handler -= value;
        }
    }     

    public static Repository Instance 
    {
        get
        {
            if (_instance == null)
            {
                _instance = new Repository();
            }
            return _instance;
        }
    }

    private Repository()
    {}

    public void Add(Game model)
    {
        string key = model.Guid.ToString();
        if (!_instance.ContainsKey(key))
        {
            _instance.Add(key, model);
            if (handler != null)
            {
                handler(this, new EventArgs());
            }                
        }       
    }
}

The handler is added in the MVC action:

Repository.Instance.OnAddItem += Repository_OnAddItem;
Repository.Instance.Add(game);

And the handler is declared in its controller:

void Repository_OnAddItem(object sender, EventArgs e)
    {
        IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<SPSHub>();
        hubContext.Clients.All.addItem();
    }

However, every time when I add item to the repository, new identical handler is added and multiplies event handling.

P.Petkov
  • 1,569
  • 1
  • 12
  • 20
  • Since your repository is a singleton, couldn't you just add the event handler once, for example on application startup? – Daniel J.G. Mar 16 '15 at 12:21
  • Lately, if I (or some other developer) want to add dynamically more handlers to this event, how should I proceed? – P.Petkov Mar 16 '15 at 12:28
  • In that case you add the new event handlers. However I was commenting that because I got the impression that you were adding the event handler every time you were adding an item to the repository – Daniel J.G. Mar 16 '15 at 12:36
  • Sorry, if I'm not clear, but my problem is with removing the handlers, not with adding them. Because it fails to remove the existed (and the same) handlers and this causes multiple re-adding of same handlers. Also I tried to implement adding of handler in the Repository constructor, but got some mysterious error, which is not the object of this discussion. – P.Petkov Mar 16 '15 at 12:42
  • [This question](http://stackoverflow.com/questions/937181/c-sharp-pattern-to-prevent-an-event-handler-hooked-twice) may help – Daniel J.G. Mar 16 '15 at 12:43
  • Actually it does not, and I will explain why. This solution relies on object comparison in the following part: `!foo.GetInvocationList().Contains(value)` Mine too in the following part: `if(handler != null)` `{ handler -= value; }` However, every time you created new (but same) handler, it cannot properly detect **it is the same handler**, which leads to: 1) not removing the handler; 2) adding the same handler again; – P.Petkov Mar 16 '15 at 12:57
  • What do you mean by _every time you created new (but same) handler_? Where is the `Repository_OnAddItem` handler declared? From that question I would say the following remark is important in your case: **delegates are defined to compare equal if they're linked to the same method on the same target object** – Daniel J.G. Mar 16 '15 at 13:09
  • Well, `void Repository_OnAddItem(object sender, EventArgs e) { IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext(); hubContext.Clients.All.addItem(); }` is defined in the MVC controller and in its action is called: `Repository.Instance.OnAddItem += Repository_OnAddItem; Repository.Instance.Add(game);` So, every time that action is requested it runs the second quoted code. If this makes different delegates by design, then I have to be more aware of .NET delegates. – P.Petkov Mar 16 '15 at 13:23
  • Yes, it will be a different handler because a new controller instance is created and used per request. However you can make that method a static one or move it into some other singleton object. That should fix your problem and you also won't need to add the handler every time you add an item to the repository (which seemed like an odd thing to me anyway), you would add it once in some sort of startup method – Daniel J.G. Mar 16 '15 at 13:57

1 Answers1

0

Thanks to Daniel J.G.:

"Yes, it will be a different handler because a new controller instance is created and used per request. However you can make that method a static one or move it into some other singleton object. That should fix your problem and you also won't need to add the handler every time you add an item to the repository (which seemed like an odd thing to me anyway), you would add it once in some sort of startup method."

Community
  • 1
  • 1
P.Petkov
  • 1,569
  • 1
  • 12
  • 20