I can suggest one possible algorithm based on memoization of a rather naive recursive algorithm, with some corner cases cleaned up. I don't know if there might be a better approach.
Convert the grammar to Chomsky normal form. Let $L(A,\ell)$ denote the set of words of length $\ell$ in $L(A)$ (i.e., all words of length $\ell$ that can be derived from $A$). We'll construct an algorithm to compute $L(S,n)$ recursively, where $S$ is the start symbol of the grammar.
The recursive algorithm for computing $L(A,\ell)$ works as follows. If we have a rule $A \to \varepsilon$ and $\ell=0$, add $\varepsilon$ to the output; for each rule $A \to a$, if $\ell=1$, add $a$ to the output; for each rule $A \to BC$ and each $0 \le i \le \ell$, add $uv$ to the output for each $u \in L(B,i)$ and $v \in L(C,\ell-i)$.
Memoize this algorithm.
As an optimization, when considering a rule $A \to BC$, only iterate over $i$ such that $0 \le i \le \ell$ and $L(B,i)$ is non-empty and $L(C,\ell-i)$ is non-empty. This prevents generating a long list of candidate values for $u$ that you'll never use. (You can precompute whether $L(A,i)$ is empty or not, for each symbol $A$ and each $0 \le i \le n$, in $O(n^2 |G|)$ time using dynamic programming, where $|G|$ is the number of rules in the grammar.) Or equivalently, when you implement the recursive algorithm, implement it using lazy lists, so that the output of $L(A,\ell)$ is a lazy list with elements generated on demand.
With this optimization, I think the total running time of this algorithm should now become something like $O(m n^2 |G|)$, where $m$ is the total number of words of length $n$ in $L$ and $|G|$ is the number of rules in the grammar. Maybe there is a tighter bound on the running time: this might be pessimistic.