For me personally the biggest benefit of this PR is to get rid of object instantiation on every single call which both solutions address. So that's cool. The only difference between your proposal and using Lazy() is that yours will still instantiate the classes on each call for **custom** factories, because you'll be calling the passed Func<> which will create the object on each call to GetFactory.

I guess what we could do to avoid Lazy<> on the public API and avoid instance-per-call is to keep your API but persist it into Lazy inside SetFactory; e.g:

    public void SetDefaultFactory(Func<T> factory)
    {
        _factories["default"] = new Lazy<T>(factory);
    }

What do you think?