/// <summary>
        /// Builds an expression for the given <paramref name="target"/>.
        /// </summary>
        /// <param name="target">The target whose expression is to be built.</param>
        /// <param name="context">The compilation context.</param>
        /// <param name="compiler">The expression compiler to be used to build any other expressions for targets
        /// which might be required by the <paramref name="target" />.  Note that unlike on the interface, where this
        /// parameter is optional, this will always be provided</param>
        protected override Expression Build(ExpressionTarget target, IExpressionCompileContext context, IExpressionCompiler compiler)
        {
            // reasonably simple - get the underlying expression, push it through the ExpressionTranslator to perform any parameter augmentations
            // or conversion to other targets (like ResolvedTarget, CconstructorTarget etc) and then push the result through a
            // TargetExpressionRewriter to compile any newly created targets into their respective expressions and into the resulting
            // expression.

            var translator = new ExpressionTranslator(context);
            var translated = translator.Visit(target.ExpressionFactory != null ? target.ExpressionFactory(context) : target.Expression);
            // the translator does lots of things - including identifying common code constructs which have rich target equivalents - such as
            // the NewExpression being the same as the ConstructorTarget.  When it creates a target in place of an expression, it wrap it
            // inside a TargetExpression - so these then have to be compiled again via the TargetExpressionRewriter.
            var targetRewriter = new TargetExpressionRewriter(compiler, context);

            return(targetRewriter.Visit(translated));
        }