Click here to Skip to main content
15,881,803 members
Please Sign up or sign in to vote.
5.00/5 (2 votes)
See more:
Hi All,

Pardon me for the relatively longer description!

I'm trying to implement the following:
A dictionary with keys as tasks of type objects, and values of type list of delegates.

The requirement is that for a given task object I might have a set of actions to be taken (Why a set? Because depending upon the task I might take multiple types of actions (dictated by their return type and parameters' types), hence a set of actions). Also, I want the user of this dictionary to be able to specify at run-time what are the actions to be taken for a specific task. Hence, I want to implement a dictionary which has task as the key and a list of delegates as the value. While adding a task-actions pair to this dictionary for a given task, if the task already exists in the dictionary then I want to first search the list of delegates for this task for the already added actions and if this new action type (delegate) already exists then I'd simply add this new action using the += operator to that delegate else I'd add a new action to the list for the task in the dictionary. If the task doesn't already exist in the dictionary then I'd simply add the task-actions pair to the dictionary. How to go about it? I have this non-compiling small sample code:

C#
class TaskActionMapping
{
    static Dictionary<object, List<Delegate>> TaskActionMapping = new Dictionary<object, List<Delegate>>();

    public static bool AddTaskAction(object task, Delegate action)
    {
        if (TaskActionMapping.ContainsKey(task))
        {
            if (TaskActionMapping[task].Contains(action))
            {
                Delegate action_set = TaskActionMapping[task][TaskActionMapping[task].IndexOf(action)];
                action_set += action;
            }
            else
            {
                TaskActionMapping[task].Add(action);
            }
        }
        else
        {
            TaskActionMapping.Add(task, new List<Delegate>();
            TaskActionMapping[task].Add(action);
        }
    }
}
Posted
Updated 23-Dec-10 1:13am
v2
Comments
Sergey Alexandrovich Kryukov 23-Dec-10 13:48pm    
The key to the solution is to define correct key for the dictionary :-)
In your sample key is object, which is not good. You really need types key.
So, how task is defined? What is is, essentially?
What is the purpose of it?

I'm asking because other people and myself implemented dictionary-based dictionary for automatic dispatching of actions in response to some object. If your purpose is similar, I'll give you the solution, if not, please explain. For now, I'll give you the general advice (see).
kjain18 23-Dec-10 22:57pm    
Thanks all for your responses! Apologies for not being v clear initially itself.

I'm trying to implement a generic producer-consumer queue (let's call it 'pcq'). I have a WinForm application which needs to handle (extract information and act on it) various types of user-defined class objects (say, for example, an instance of StudentData class which could have all the performance related information of the student for all the previous years and my application would be asked to draw a graph of the performance for the student). Please note that application may not be aware either of the request type (that's why task type is object), or of the kind or number of actions to be taken (that's why user of the application passes a multicast delegate to the application). Application, hence, essentially provides a 'pcq' for processing user-defined tasks in user-defined manner. The purpose of sharing a dictionary between the user and the application was for the application to dispatch the correct delegates for a given task object upon its processing in the pcq's consumer thread. The dictionary is populated with task-type and multicast delegates before initializing the pcq.

My application would want to do it in a serial manner for all the incoming requests (a request contains an instance of, say StudentData class, BUT can also contain an object of type EmployeeData class, for which the processing would of course be different), and on another thread than the main GUI thread (hence the choice of pcq).
Sergey Alexandrovich Kryukov 25-Dec-10 0:33am    
Interesting approach. At first glance it looks to me as quite reasonable and productive; and you got my 5 for the question. Maybe, it needs more thinking to make a cleaner, more effective and supportable design of the technique.

I still think my basic recommendation to make key a generic parameter should help. This generic type could also be classified to have some common base class or interface (via "where" specification) to rely upon.

Also, if I decide to publish an article my old and trusty dynamic dispatch generic classes -- kind of close topic -- you might find it useful to see, just for exchange of ideas.

Best wished in New Year!

A couple of things.

1. You can't have a type name with the same name as the class it belongs to.
2. Why not change Delegate into MulticaseDelegate in the line:
C#
static Dictionary<object, List<Delegate>> TaskActionMapping = new Dictionary<object, List<Delegate>>();
 
Share this answer
 
Comments
kjain18 23-Dec-10 23:01pm    
Thanks Pete! You're right about both '1' and '2'.
Instead of using object task, make your class generic:

C#
class TaskActionMapping<task> where TASK : ??? /**/ {
   public void Add(TASK task, System.Func<TASK, bool> action) { /*...*/}
   // System.Func instead of Delegate.
   // bool is return value, but you can use another generic parameter 
}</task>


For multi-casting, it could work like this: if an action for this key is not in dictionary, new list of delegates is added (better be Queue), if one is already in dictionary, enqueue another delegate to existing queue.

Please see my questions in my comment to the question.
 
Share this answer
 
v5
Comments
Sergey Alexandrovich Kryukov 23-Dec-10 13:58pm    
If you're not catching the idea but it seems close to what you need... perhaps I'll need to write a whole article on the topic. Or, just ask me questions (but please provide more background on your problem, as I asked.
Espen Harlinn 26-Feb-11 11:08am    
Good idea, my 5
Sergey Alexandrovich Kryukov 26-Feb-11 19:22pm    
Thank you, Espen.
I'm preparing my article on the topic, more advanced than that; I've used it for quite a while before.
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900