A General Case
In this post we are going to take the Photo Processor example and change the names to more general names so that we can better apply Delegates to our own code by taking this general case and changing the code to suit our objects. For example, in this code we have called our class MyClass and given it two properties and a method. Here, we won’t use the method but we will use the two properties.
This program has the following four files:
- MyClass
- MyClassMethods
- MyClassProcessor
- Program
We have a project called DelegatesGeneral. Below is the class. For your project all you have to do is change the name of MyClass and the names of the properties and methods in this code to suit your project. Add more properties and methods as needed.
MyClass
namespace DelegatesGeneral { class MyClass { public string MyString { get; set; } public int MyInt { get; set; } public static MyClass MyClassDoMethod() { return new MyClass(); // we don't use this } } }
Library Methods
We’ve written a few methods that take in our class and perform something on it by changing one property. The class is called MyClassMethods. Your code could do whatever you needed it to do.
using System; namespace DelegatesGeneral { class MyClassMethods { // Library // // this is like a library of methods we have that operate on // our class called MyClass. // the consumer of our software (Main) can write their own library // and use those methods with our software, making our // software extensible and flexible, similar to a Framework. public void AddOne(MyClass mc) { // here we do something with the object mc mc.MyInt = mc.MyInt + 1; Console.WriteLine("AddOne: " + mc.MyString + " " + mc.MyInt); } public void DoubleIt(MyClass mc) { mc.MyInt = mc.MyInt * 2; Console.WriteLine("DoubleIt: " + mc.MyString + " " + mc.MyInt); } public void AppendString(MyClass mc) { mc.MyString = mc.MyString + " appending this string now "; Console.WriteLine("AppendString: " + mc.MyString + " " + mc.MyInt); } } }
MyClassProcessor
using System; namespace DelegatesGeneral { class MyClassProcessor { public int MyAmount { get; set; } public void Process(Action<MyClass> methodHandler) { // methodHandler is a delegate // instantiate it and use object initialization syntax // to set the two properties var myclass = new MyClass { MyString = "inside Process method ", MyInt = 1 }; methodHandler(myclass); // we do not define the methods we want to run here because // we are going to let the consumer define that. } } }
Program
using System; namespace DelegatesGeneral { class Program { static void Main(string[] args) { // Main is the consumer var myclassprocessor = new MyClassProcessor(); var myclassmethods = new MyClassMethods(); Action<MyClass> methodHandler = myclassmethods.AddOne; // methodHandler is a pointer to a group of functions (delegate) methodHandler += myclassmethods.DoubleIt; methodHandler += FromConsumerMinusOne; // Here is the whole point of this! Extensible! methodHandler += myclassmethods.AppendString; Console.WriteLine("Generic Delegate Action:"); myclassprocessor.Process(methodHandler); // Process() takes a delegate } static void FromConsumerMinusOne(MyClass myC) { myC.MyInt = myC.MyInt - 1; Console.WriteLine("FromConsumerMinusOne: " + myC.MyString + myC.MyInt); } } }
Instantiate the Class in Program
Alternatively we could instantiate our class in the main program and pass it to the Process method, instead of instantiating it in the Process method. How would that look?
using System; namespace DelegatesGeneral { class Program { static void Main(string[] args) { // Main is the consumer var myclassprocessor = new MyClassProcessor(); var myclassmethods = new MyClassMethods(); Action<MyClass> methodHandler = myclassmethods.AddOne; // methodHandler is a pointer to a group of functions (delegate) methodHandler += myclassmethods.DoubleIt; methodHandler += FromConsumerMinusOne; // Here is the whole point of this! Extensible! methodHandler += myclassmethods.AppendString; Console.WriteLine("Generic Delegate Action:"); // instantiate the class here (line below) var myclass = new MyClass { MyString = "inside Main() ", MyInt = 10 }; myclassprocessor.Process(methodHandler, myclass); // Process() takes a delegate } static void FromConsumerMinusOne(MyClass myC) { myC.MyInt = myC.MyInt - 1; Console.WriteLine("FromConsumerMinusOne: " + myC.MyString + myC.MyInt); } } }
using System; namespace DelegatesGeneral { class MyClassProcessor { public int MyAmount { get; set; } public void Process(Action<MyClass> methodHandler, MyClass myclass) { // methodHandler is a delegate // instantiate MyClass and use object initialization syntax // to set the two properties //var myclass = new MyClass { MyString = "inside Process method ", MyInt = 1 }; methodHandler(myclass); // we do not define the methods we want to run here because // we are going to let the consumer define that. } } }