Search code examples
c#design-patternsdelegatestable-driven

How can i use Table Driven methods with delegate and Dictionary?


Hi i have been exhausted too many if comparization. and switch case methods. i have been read below issue:

Best table / enum driven method calling system

this usage is good. Look Vivek's responses.

My usage Below but i can not this.


namespace DelegateKavrami
{
    class Program
    {
        static void Main(string[] args)
        {

            new MyTest().Run();
            Console.Read();
        }

    }


    public class MyTest
    {
        public void Run()
        {
            MyMessageProcessor myProcessor = new MyMessageProcessor();
            myProcessor.Register(0, Sms);
            myProcessor.Register(1, Mms);
            myProcessor.ProcessMessage(1, Message.Sms);

        }
        public void Sms(Message message)
        {
            Console.WriteLine("Sms olarak gönderilen mesaj");
        }
        void Mms(Message message)
        {
            Console.WriteLine("Mms olarak gönderilen mesaj:");
        }

    }

    public class MyMessageProcessor
    {
        public delegate void ProcessMessageDelegate(Message message);

        Dictionary methods;

        public void Register(int messageType,
                              ProcessMessageDelegate processMessage)
        {
            methods[messageType] = processMessage;
        }

        public void ProcessMessage(int messageType, Message message)
        {
            if (methods.ContainsKey(messageType))
            {
                methods[messageType](message);
            }
        }
    }

    public enum Message
    {
        Sms,Mms
    }

}

But my Dream

myProcessor.ProcessMessage(1)

How can i use this? Error after above code runnig: Object reference not set to an instance of an object. ON methods[messageType] = processMessage;


Solution

  • Refactor your code a little bit, rather than using delegate, template pattern should be better:

    public enum messageType
    {
        Sms, Mms
    }
    
    public class Message
    {
        public MessageType MessageType { get; get; }
        public string Data { get; set; } // assume data to be processed
    }
    
    
    interface IHandler
    {
        void Process(Message message);
    }
    
    class SmsHander : IHandler
    {
        void Process(Message message)
        {}
    }
    
    class MmsHander : IHandler
    {
        void Process(Message message)
        {}
    }
    
    class MessageProcessor
    {
        private Dictionary<MessageType, IHandler> 
                       handlers = new Dictionary<MessageType, IHandler>()
        {
            { MessageType.Sms, new SmsHander() },
            { MessageType.Mms, new MmsHander() },
        };
    
        public void Process(Message message)
        {
            handlers[message.MessageType].Process(message);
        }
    }
    

    So, you can call:

    var processor = new Processor();
    processor.Process(message);