protected override Expression VisitMember(MemberExpression node)
        {
            Expression newNode = null;

            if (evaluator.EnsureKnownType(
                    node.Member,
                    replaceCompilerGeneratedType: _ =>
            {
                newNode = evaluator.EvaluateCompilerGenerated(node, protocol)
                          ?? CompilerGenerated.Get(
                    Visit(node.Expression),
                    node.Member,
                    type =>
                {
                    evaluator.EnsureKnownType(
                        type,
                        replaceCompilerGeneratedType: __ => type = typeof(CompilerGenerated),
                        genericArgumentsUpdated: updatedType => type = updatedType);

                    return(type);
                });
            },
                    unknownType: (_, __) => newNode = evaluator.GetValue(node, this, protocol)))
            {
                return(newNode);
            }
            else
            {
                return(base.VisitMember(node));
            }
        }
        protected override Expression VisitNew(NewExpression node)
        {
            NewExpression newNode = null;

            if (evaluator.EnsureKnownType(
                    node.Constructor,
                    replaceCompilerGeneratedType: _ => newNode = CompilerGenerated.New(node.Members, Visit(node.Arguments)),
                    genericArgumentsUpdated: updatedType =>
            {
                /* Overload resolution should be unaffected here, so keep the same constructor index.  We're just swapping a
                 * compiler-generated type for the internal CompilerGenerated class, neither of which can be statically
                 * referenced by users.
                 */
                var flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;

                var oldConstructorIndex = Array.IndexOf(node.Constructor.DeclaringType.GetConstructors(flags), node.Constructor);
                var newConstructor = updatedType.GetConstructors(flags)[oldConstructorIndex];

                newNode = Expression.New(newConstructor, Visit(node.Arguments), node.Members);
            }))
            {
                return(newNode);
            }

            return(base.VisitNew(node));
        }
        protected override Expression VisitBinary(BinaryExpression node)
        {
            if (node.NodeType == ExpressionType.Assign)
            {
                MethodCallExpression newNode = null;

                if (evaluator.EnsureKnownType(
                        node.Left.Type,
                        replaceCompilerGeneratedType: _ => newNode = CompilerGenerated.Set(Visit(node.Left), Visit(node.Right))))
                {
                    return(newNode);
                }
            }

            return(base.VisitBinary(node));
        }