C# What construct am I Looking for Lamba / Expression / Func / Reflection for runtime property substitution?
I've a method on a generic base class that I want to execute for all superclasses of it
The logic is something like:
BuildAverageDateStats(List<type> items, DateProperty1 exp, DateProperty2 exp2)
{
return new Stat{
Value = items.Average(c => (c.DateProperty2 - c.DateProperty1).Milliseconds)
};
}
myobject.BuildAverageDateStats(list, () => c.QueuedDate, () => c.CompletedDate);
myobject.BuildAverageDateStats(list, () => c.ActionedDate, () => c.CompletedDate);
开发者_C百科
I think I need expressions, but not sure how...
I could send it in as Func i.e. Value = items.Average(c => myfunc(c))
but looking for a property substitution example.
Stat BuildAverageDateStats<U>(List<type> items, Func<U, double> exp)
where U:type
{
return new Stat{
Value = items.OfType<U>().Average(exp);
};
}
You can call it like this
BuidlAverageDateStats<Dog>(items, d=>d.Age - d.Height);
Though my example doesn't make sense.
If you are really only ever going to use one of the three DateTime properties that you have right now, I would keep the method signature the way you have it right now. To make things neater, make some public static readonly delegate fields on your class for your properties, and use those, instead of writing the same expression time and time again:
public static readonly DateSelector Date1Property = delegate(CompareTest c) { return c.Date1; };
public static readonly DateSelector Date2Property = delegate(CompareTest c) { return c.Date2; };
public static readonly DateSelector Date3Property = delegate(CompareTest c) { return c.Date3; };
If, on the other hand, you expect inheriting classes to implement more properties than the three you have right now, you could consider passing in the properties as String and using the Dynamic Linq Library (and build a dynamic expression that returns the property) or a DynamicMethod to return your property. Both would have the benefits of reflection with the painful performance. If you need it, I have some code laying around for that. Type safety will be out the window though, so I wouldn't use it unless necessary, and it sounds like it isn't.
Menno
static Stat BuildAverageDateStats<T>(List<T> items, string pname1, string pname2){
return new Stat {
Value = items.Average( c =>
{
var ty = c.GetType();
var pv1 = (dynamic)ty.GetProperty(pname1).GetValue(c,null);
var pv2 = (dynamic)ty.GetProperty(pname2).GetValue(c,null);
return pv2 - pv1;
})
};
}
精彩评论