I have close to a hundred classes where I need to get arbitrary properties from them at runtime. The calling class knows which properties it wants at run time, but not at compile time. Looking for any suggestions on a quick way to do this.
My ideas so far:
Option 1: Add "public object Get(string prop) {...}" to all classes, then invoke myClass.Get(prop)
Option 2: Use reflection: typeof(myClass).GetProperty(prop).GetValue(myClass)
Option 3: Use ComponentModel: TypeDescriptor.GetProperties(typeof(myClass))[prop].GetValue(myClass);
Option 4: HyperTypeDescriptionProvider
Trying these out gave me runtimes of:
301ms (baseline accessing the property directly)
1308ms Option 1
4383ms Option 2
5229ms Option 3
Option 4 threw System.TypeInitializationException constantly and never completed.
Full Executable sample:
//using Hyper.ComponentModel;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
namespace Sandbox2
{
public class MyTable
{
public string col0 {get;set;}
public int col1 { get; set; }
public string[] col2 { get; set; }
public object col3 { get; set; }
public string col4 { get; set; }
public object Get(string prop)
{
switch(prop)
{
case "col0":
return col0;
case "col1":
return col1;
case "col2":
return col2;
case "col3":
return col3;
case "col4":
return col4;
}
throw new InvalidOperationException("Non-existent prop");
}
}
class Program
{
static void Main(string[] args)
{
const int CYCLES = 5000000;
//const int CYCLES = 1;
GC.Collect();
Stopwatch timer = new Stopwatch();
string[] goalProps = { "col2", "col0", "col4" };
MyTable myTable = new MyTable();
timer.Start();
for (int i = 0; i < CYCLES; ++i)
{
object[] res = { myTable.col2, myTable.col0, myTable.col4 };
}
timer.Stop();
System.Diagnostics.Debug.WriteLine("Elapsed: " + timer.ElapsedMilliseconds);
GC.Collect();
timer.Start();
for (int i=0; i<CYCLES; ++i)
{
object[] res = { myTable.Get(goalProps[0]), myTable.Get(goalProps[1]), myTable.Get(goalProps[2]) };
}
timer.Stop();
System.Diagnostics.Debug.WriteLine("Elapsed: " + timer.ElapsedMilliseconds);
timer.Reset();
GC.Collect();
timer.Start();
for (int i = 0; i < CYCLES; ++i)
{
Type t = myTable.GetType();
PropertyInfo[] goalPropsInfo = { t.GetProperty(goalProps[0]), t.GetProperty(goalProps[1]), t.GetProperty(goalProps[2]) };
object[] res = { goalPropsInfo[0].GetValue(myTable), goalPropsInfo[1].GetValue(myTable), goalPropsInfo[2].GetValue(myTable) };
}
timer.Stop();
System.Diagnostics.Debug.WriteLine("Elapsed: " + timer.ElapsedMilliseconds);
timer.Reset();
GC.Collect();
timer.Start();
for (int i = 0; i < CYCLES; ++i)
{
Type t = myTable.GetType();
//HyperTypeDescriptionProvider.Add(t);
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(t);
PropertyDescriptor[] goalPropsInfo = { props[goalProps[0]], props[goalProps[1]], props[goalProps[2]] };
object[] res = { goalPropsInfo[0].GetValue(myTable), goalPropsInfo[1].GetValue(myTable), goalPropsInfo[2].GetValue(myTable) };
}
timer.Stop();
System.Diagnostics.Debug.WriteLine("Elapsed: " + timer.ElapsedMilliseconds);
}
}
}
````
Dictionary<string, T>
to set and get values by name in runtime? \$\endgroup\$