Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Michel Perfetti, has taken my little Maybe thingie and gone a lot further,
by using expression tree re-writting he has made it possible to express this:
string code = licensePlate.Maybe(lp => lp.Car)
.Maybe(c => c.Owner)
.Maybe(o => o.Address)
.Maybe(a => a.PostCode);
which is NULL safe but very cumbersome like this:
string code = licensePlate.Maybe2(lp => lp.Car.Owner.Address.PostCode);
which is much cleaner and still NULL safe.
Michel does this by declaring Maybe2 to take an Expression, rather than a Func i.e. it has this signature: public static V Maybe2<T, V>(this T t, Expression<Func<T, V>> expression)
Then he cracks open the expression and rewrites it to do each property access inside a call to Maybe.
Nice stuff Michel.
UPDATE: Sorry for originally getting your last name wrong Michel, and thanks Matthieu for pointing it out!
Comments
Anonymous
March 03, 2008
PingBack from http://msdnrss.thecoderblogs.com/2008/03/03/maybe-there-is-more/Anonymous
March 05, 2008
I just had to try this one step further :P public static class Null { private static readonly MethodInfo maybeMethod; static Null() { maybeMethod = typeof(Null).GetMethod("Maybe", BindingFlags.Public | BindingFlags.Static); } public static V Maybe<T, V>(this T t, Func<T, V> selector) where T : class { return t != null ? selector(t) : default(V); } public static T Try<T>(Expression<Func<T>> ex) { MemberExpression memberBody = ex.Body as MemberExpression; if (memberBody != null) { MethodCallExpression result = ConvertMemberToMethodCall(memberBody); LambdaExpression lambda = Expression.Lambda(result); return (T)lambda.Compile().DynamicInvoke(); } throw new NotSupportedException(); } private static MethodCallExpression ConvertMemberToMethodCall(MemberExpression memberExpression) { MemberExpression me = memberExpression.Expression as MemberExpression; Expression ex = me != null ? ConvertMemberToMethodCall(me) : memberExpression.Expression; Type type = null; PropertyInfo prop = memberExpression.Member as PropertyInfo; if (prop != null) { type = prop.PropertyType; } else { FieldInfo field = memberExpression.Member as FieldInfo; if (field != null) { type = field.FieldType; } } if (type == null) { throw new NotImplementedException(); } MethodInfo methodInfo = maybeMethod.MakeGenericMethod(new[] { memberExpression.Member.DeclaringType, type }); ParameterExpression p = Expression.Parameter(memberExpression.Member.DeclaringType, "p"); LambdaExpression maybeLamba = Expression.Lambda(Expression.MakeMemberAccess(p, memberExpression.Member), new[] { p }); return Expression.Call(null, methodInfo, new[] { ex, maybeLamba }); } } Which can be used as: string testString = "Test"; int length4 = Null.Try(() => testString.Length); // 4 string nullString = null; int length0 = Null.Try(() => nullString.Length); // 0Anonymous
March 06, 2008
@XIU,that is pretty cool. Nice workAlex