Reputation: 3857
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.
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
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
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
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