/// <summary> /// Returns a new delegate that safely gets the result of the specified expression /// fragments. /// </summary> /// <typeparam name="TSource">The instance type.</typeparam> /// <typeparam name="TResult">The result type.</typeparam> /// <param name="expressionFragments">The expression fragments, which will be processed in the order as specified.</param> /// <returns>The result or the default value of the result type, if one or more of the referenced members in the expression are <c>null</c>.</returns> private static Func <TSource, TResult> CreateSafeGetDelegate <TSource, TResult>(IList <MemberExpression> expressionFragments) { List <Expression> targetFragments = new List <Expression>(); MemberExpression lastSourceFragment = expressionFragments.Last(); ParameterExpression instanceParameter = Expression.Variable(typeof(object), "instance"); ParameterExpression resultVariable = Expression.Variable(typeof(TResult), "result"); LabelTarget useDefaultLabel = Expression.Label("useDefault"); LabelTarget returnLabel = Expression.Label("return"); foreach (MemberExpression sourceFragment in expressionFragments) { MemberInfo memberInfo = (MemberInfo)sourceFragment.Member; MemberExpression member = ConstantExpression.MakeMemberAccess( Expression.Convert(instanceParameter, memberInfo.DeclaringType), memberInfo); if (sourceFragment != lastSourceFragment) { // Iterate into the member. targetFragments.Add( Expression.Assign( instanceParameter, Expression.Convert(member, typeof(object)))); // Value types cannot represent a null reference. if (sourceFragment.Type.IsClass) { targetFragments.Add( Expression.IfThen( Expression.Equal(instanceParameter, Expression.Constant(null)), Expression.Goto(useDefaultLabel))); } } else { // The value of the final member is the actual result. targetFragments.Add( Expression.Assign( resultVariable, Expression.Convert(member, typeof(TResult)))); } } targetFragments.Add(Expression.Goto(returnLabel)); targetFragments.Add(Expression.Label(useDefaultLabel)); targetFragments.Add(Expression.Assign(resultVariable, Expression.Default(typeof(TResult)))); targetFragments.Add(Expression.Label(returnLabel)); targetFragments.Add(resultVariable); Expression finalExpression = Expression.Block(new[] { resultVariable }, targetFragments); return(Expression.Lambda <Func <TSource, TResult> >(finalExpression, instanceParameter).Compile()); }