Kickaha
Kickaha

Reputation: 3857

accessing class properties and methods with a string representation of the property name

I have a class which has a bunch of collections

Class MyInfoClass
{

Queue<float> firstQ = new Queue<float>();
Queue<float> secondQ = new Queue<float>();
Queue<float> thirdQ = new Queue<float>();
Queue<float> fourthQ = new Queue<float>();
Queue<float> fifthQ = new Queue<float>();

} 

And another which has a string representation of the names of those collections

class myParamClass
{
 internal static string[] Chain =
        {
            "firstQ", 
            "secondQ",
            "thirdQ", 
            "fourthQ",
            "fifthQ"
        }           
}

I want to access the collections using the string representations

class Program
    {
        static void Main(string[] args)
        {
            MyInfoClass myInfoChain = new MyInfoClass();

            float i = 0;

            //attempt to set 
            foreach (string qName in MyParamClass.Chain)
            {
                i++;
                myInfoChain.GetType().GetProperty(qName).SetValue(myInfoChain,i);
            }
            //attempt to get
            foreach (string qName in MyParamClass.Chain)
            {
                Trace.WriteLine(myInfoChain.GetType().GetProperty(qName).GetValue(myInfoChain,null));
            }

        }
    }

I'm trying to use reflection but keep getting null object exceptions, but don't really care how I achieve this. I tried using an enum but hat was over complicating things, I've tried exposing the fields as properties and invoking the get set methods. I'm going round and round like a hamster.

Specifically I need to know how to access the collections as above, but in general how to I access the members (properties/field/method) of a class using a string of the (property/field/method) name would be very useful?

What I have read keeps pointing to something like var letMeIn = typeof (MyInfoClass).GetProperty("_firstQ").GetValue(myInfoChain,null); ????

but GetProperty("_firstQ") is null no matter what I do.

Any help is appreciated.

Resolved as follows

With respect to reflection exposing the queues as properties and using this was a good solution,

   var letMeIn =  typeof (MyInfoClass).GetProperty("FirstQ")
                      .GetValue(myInfoChain,null);
... but I never managed to get the matching .SetValue() method working.


What worked really well was the array of Queues
class MyInfoClass
{
    private Queue<float> _firstQ = new Queue<float>();
    private Queue<float> _secondQ = new Queue<float>();
    private Queue<float> _thirdQ = new Queue<float>();
    private Queue<float> _fourthQ = new Queue<float>();
    private Queue<float> _fifthQ = new Queue<float>();

    public Queue<float>[] MyQueues
    {
        get
        {
            return new[] { _firstQ, _secondQ, _thirdQ, _fourthQ, _fifthQ };
        }
    }
} 
Which allowed me to iterate the collections byte index, and also to 

leverage LINQ in recusive loops (my core objective) as shown below .

    class Program
    {

        static List<double> SeperateWorkMethod(List<double> d, float val)
        {
            //stuff/work on d, List<double>
            return d;
        }

        static void Main(string[] args)
        {
            MyInfoClass myInfoChain = new MyInfoClass();
            float x = 0;

            List<double> temp = new List<double>();

            foreach (Queue<float> t in myInfoChain.MyQueues)
            {
                x = x + 123;
                t.Enqueue(x);
                temp.Add(t.Average());
                temp.AddRange(t.Select(subType => subType.customField));
            }

            for (int index = 0; index < myInfoChain.MyQueues.Length; index++)
            {
                myInfoChain.MyQueues[index].Aggregate(temp, SeperateWorkMethod);
            }
        }
    }
}

I still feel like I should use an enum here somewhere, but the puzzle is solved for now. Many thanks to all.

Upvotes: 1

Views: 58

Answers (3)

Steve Lillis
Steve Lillis

Reputation: 3256

At the moment your queues are fields, not properties. Try defining them as

FirstQ { get; set; }

and assigning the queue in the constructor. Then GetProperty("FirstQ") should get you what you need.

Upvotes: 1

Heinzi
Heinzi

Reputation: 172270

but GetProperty("_firstQ") is null no matter what I do.

That's because you don't have a property _firstQ. Add one... (in addition to your fields)

public Queue<float> _firstQ { get { return firstQ; } }

and your code example above should work.

Note, though, that in C# properties usually start with an upper-case letter, so

public Queue<float> FirstQ { get { return firstQ; } }

would be more idiomatic.


In fact, if all you need to do is access the n-th queue dynamically, you don't need reflection at all:

public Queue<float>[] MyQueues
{ 
    get 
    {
        return new[] { firstQ, secondQ, thirdQ, fourthQ, fifthQ };
    }
}

and you can just access the n-th queue as myInfoChain.MyQueues[n]... no reflection needed.

Upvotes: 2

Selman Gen&#231;
Selman Gen&#231;

Reputation: 101681

You don't have properties, you have fields. So you need GetField method instead.Also the fields are private, you need to specify BindingFlags.NonPublic flag:

myInfoChain.GetType()
.GetField(qName, BindingFlags.Instance | BindingFlags.NonPublic)
.SetValue(myInfoChain,i);

Upvotes: 3

Related Questions