Created
October 8, 2013 13:37
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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