Click here to Skip to main content
15,896,118 members
Articles / Programming Languages / C#

Generic Dynamic Methods Primer

Rate me:
Please Sign up or sign in to vote.
4.60/5 (8 votes)
23 Aug 2007CPOL3 min read 37.6K   154   40  
Sample how to use generics and dynamic methods together to get simple type safe access to private variables
using System;
using System.Collections.Generic;

namespace DynamicMethodsTest
{
    //first sample class.
    //Note - variables are private
    class SampleA 
    {
        private int m_value;
        private List<string> m_list;
        
        public SampleA(int a)
        {
            Value = a;
        }


        public int Value
        {
            get { return m_value; }
            set { m_value = value; }
        }

        public List<string> List
        {
            get { return m_list; }
            set { m_list = value; }
        }
    }

    //second sample class
    //note - completely different type, variable is private
    class SampleB
    {
        private int m_anotherValue;

        public SampleB(int a)
        {
            m_anotherValue = a;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //create first test instance
            SampleA sampleA = new SampleA(17);

            //create get/set accessors that can work on int field "m_value" on any instance
            AccessorBuilder.GetFieldValueUnboundDelegate<int, SampleA> valueGetter =
                AccessorBuilder.CreateGetter<int, SampleA>("m_value");
            AccessorBuilder.SetFieldValueUnboundDelegate<int, SampleA> valueSetter =
                AccessorBuilder.CreateSetter<int, SampleA>("m_value");

            //fetch value
            int value = valueGetter(sampleA);

            Console.WriteLine(value);

            //change value
            valueSetter(sampleA, 23);

            Console.WriteLine(sampleA.Value);

            //verify
            value = valueGetter(sampleA);
            Console.WriteLine(value);

            //create get/set accessors for generic list field, they also can work on any instance
            AccessorBuilder.GetFieldValueUnboundDelegate<List<string>, SampleA> listGetter =
                AccessorBuilder.CreateGetter<List<string>, SampleA>("m_list");
            AccessorBuilder.SetFieldValueUnboundDelegate<List<string>, SampleA> listSetter =
                AccessorBuilder.CreateSetter<List<string>, SampleA>("m_list");

            //get initial null reference
            List<string> list = listGetter(sampleA);

            Console.WriteLine(list);

            list = new List<string>();
            list.Add("aaa");
            list.Add("bbb");

            //modify 
            listSetter(sampleA, list);

            //fetch and print
            sampleA.List.ForEach(delegate(string item) { Console.WriteLine(item); });

            //create instance bound delegates for list values
            AccessorBuilder.GetFieldValueBoundDelegate<List<string>> instanceListGetter =
                AccessorBuilder.CreateGetter<List<string>, SampleA>(sampleA, "m_list");
            AccessorBuilder.SetFieldValueBoundDelegate<List<string>> instanceListSetter =
                AccessorBuilder.CreateSetter<List<string>, SampleA>(sampleA, "m_list");

            //note - we do not pass instance to delegate, it retrieves field value from sampleA
            instanceListGetter().ForEach(delegate(string item) { Console.WriteLine(item); });

            //modify
            instanceListSetter(new List<string>(new string[]
                                                    {
                                                        "111",
                                                        "222"
                                                    }));

            //verify
            instanceListGetter().ForEach(delegate(string item) { Console.WriteLine(item); });

            //demonstrate pseudo-polymorphic handling
            //we have 2 classes, both expose (actually hide) int variable
            //we can work with them like they both implement some interface

            //define instance bound get/set accessors for int field of SampleA
            AccessorBuilder.GetFieldValueBoundDelegate<int> instanceValueGetterA =
                AccessorBuilder.CreateGetter<int, SampleA>(sampleA, "m_value");
            AccessorBuilder.SetFieldValueBoundDelegate<int> instanceValueSetterA =
                AccessorBuilder.CreateSetter<int, SampleA>(sampleA, "m_value");

            SampleB sampleB = new SampleB(55);

            //define instance bound get/set accessors for int field of SampleB
            AccessorBuilder.GetFieldValueBoundDelegate<int> instanceValueGetterB =
                AccessorBuilder.CreateGetter<int, SampleB>(sampleB, "m_anotherValue");
            AccessorBuilder.SetFieldValueBoundDelegate<int> instanceValueSetterB =
                AccessorBuilder.CreateSetter<int, SampleB>(sampleB, "m_anotherValue");


            //store setters in type safe list
            List<AccessorBuilder.SetFieldValueBoundDelegate<int>> uniformSet =
                new List<AccessorBuilder.SetFieldValueBoundDelegate<int>>();

            uniformSet.Add(instanceValueSetterA);
            uniformSet.Add(instanceValueSetterB);

            //store getters in type safe list
            List<AccessorBuilder.GetFieldValueBoundDelegate<int>> uniformGet =
                new List<AccessorBuilder.GetFieldValueBoundDelegate<int>>();

            uniformGet.Add(instanceValueGetterA);
            uniformGet.Add(instanceValueGetterB);

            //initialize both variables to 43
            uniformSet.ForEach(delegate(AccessorBuilder.SetFieldValueBoundDelegate<int> item) { item(43); });

            //get and print
            uniformGet.ForEach(
                delegate(AccessorBuilder.GetFieldValueBoundDelegate<int> item)
                    {
                        int v = item();
                        Console.WriteLine("{0}={1}", item.Target.GetType().Name, v);
                    });
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Architect mPrest Systems
Israel Israel
I am working with various Microsoft technologies since 1994 (remember Windows 3.1 ?Smile | :) ). Language of choice - C++/C#. I am mainly interested in software engineering and "generic solutions", so frequently I find myself designing / implementing frameworks and application skeletons, although sometimes I do various stuff from DB to Kernel Mode device drivers. I also love to understand why things are in the way they are, not just how to use them.
Currently I am Chief Software Architect and CTO of the software outsourcing company mPrest Ltd , Israel.

Comments and Discussions