Skip to content

Instantly share code, notes, and snippets.

@zaus
Created October 8, 2013 13:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save zaus/6884806 to your computer and use it in GitHub Desktop.
Save zaus/6884806 to your computer and use it in GitHub Desktop.
Comparing results of Nested Property/Field extraction via Reflection or Expression Tree; testing in LinqPad -- from http://stackoverflow.com/questions/536932/how-to-create-expression-tree-lambda-for-a-deep-property-from-a-string
public static class ObjectExtensions {
public static object ReflectValue(this object o, string path) {
// http://stackoverflow.com/a/4474015/1037948
return path.Split('.').Aggregate(o, (current, component) => {
var property = current.GetType().GetProperty(component);
if(null == property) {
var field = current.GetType().GetField(component);
if(null == field) return null;
return field.GetValue(current);
}
return property.GetValue(current, null);
});
}
public static Func<TObj, TValue> ExpressValue<TObj, TValue>(this TObj o, string fieldname) {
// simplified from example - http://marcgravell.blogspot.com/2008/10/express-yourself.html
// modified for nested properties via http://stackoverflow.com/questions/13613648/nested-property-in-expression-tree and http://stackoverflow.com/a/537189/1037948
// alias to model
var m = Expression.Parameter(typeof(TObj), "m");
// the model property we want
/*Member*/Expression expr = m;
// break up nested property
expr = fieldname.Contains(".")
? fieldname.Split('.').Aggregate(expr, Expression.PropertyOrField)
: Expression.PropertyOrField(m, fieldname);
return Expression.Lambda<Func<TObj, TValue>>(expr, m).Compile();
}
}
/// <summary> Performance check -- how long do X repetitions of a task take?</summary>
public static long Perf(this string reportTitle, Action<int> task, int repetitions = 10000) {
// http://stackoverflow.com/questions/28637/is-datetime-now-the-best-way-to-measure-a-functions-performance
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < repetitions; i++) {
task(i);
}
sw.Stop();
string.Format("{0} ticks elapsed ({1} ms)", sw.Elapsed.Ticks, sw.Elapsed.TotalMilliseconds).Dump(string.Format("{0} ({1}x)", reportTitle, repetitions));
return sw.Elapsed.Ticks;
}
void Main()
{
var t1 = Foo.Create(1);
var field = "Sub.Sub.Sub.ID.N";
string.Format("Reflect {0}", field).Perf(n => testReflect(t1, field, false));
string.Format("Express {0}", field).Perf(n => testExpress(t1, field, false));
t1.Dump("Test Foo 1");
testReflect(t1, "ID.N", true);
testReflect(t1, "Sub.ID.N", true);
testReflect(t1, "Sub.Sub.ID.N", true);
testReflect(t1, "Sub.Sub.Sub.ID.N", true);
testExpress(t1, "ID.N", true);
testExpress(t1, "Sub.ID.N", true);
testExpress(t1, "Sub.Sub.ID.N", true);
testExpress(t1, "Sub.Sub.Sub.ID.N", true);
}
// Define other methods and classes here
void testReflect(object o, string property, bool isDump = false) {
var p = o.ReflectValue(property);
if(isDump) p.Dump("Reflect " + property);
}
void testExpress(Foo o, string property, bool isDump = false) {
var p = o.ExpressValue<Foo, string>(property)(o);
if(isDump) p.Dump("Express " + property);
}
public struct Iota
{
public string N;
public int ID;
public Iota(string n, int id) { this.N = n; this.ID = id; }
public static Iota Create(int i = 0) { var t = (int)(DateTime.UtcNow.Ticks - 621355968000000000) + i; return new Iota("" + (char)((t%26) + 'a'), t); }
}
public struct Foo
{
public string N;
public Bar Sub;
public Iota ID;
public Foo(string n, Bar b, Iota id) { this.N = n; this.ID = id; this.Sub = b; }
public static Foo Create(int n)
{
return new Foo("foo" + n, new Bar("bar" + n, new Baz("baz" + n, new Fon("fon" + n, Iota.Create(n)), Iota.Create(n + 1)), Iota.Create(n + 2)), Iota.Create(n+3));
}
}
public struct Bar
{
public string N;
public Baz Sub;
public Iota ID;
public Bar(string n, Baz b, Iota id) { this.N = n; this.ID = id; this.Sub = b; }
}
public struct Baz
{
public string N;
public Fon Sub;
public Iota ID;
public Baz(string n, Fon b, Iota id) { this.N = n; this.ID = id; this.Sub = b; }
}
public struct Fon
{
public string N;
public Iota ID;
public Fon(string n, Iota id) { this.N = n; this.ID = id; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment