The rule of thumb I often use is that I inject things that are in the way of properly writing unit tests. When doing this you will sometimes end up abstracting away BCL classes (such as DateTime.Now, File, etc), and sometimes your own stuff. Good things to inject are services (such as ICustomerService, ICustomerUnitOfWorkFactory, or ICustomerRepository). Don't inject things like entities, DTOs and messages.
There are other reasons for injecting objects however, such as to be able to replace modules at a later time (for instance switch implementations for validation, UI, or O/RM), to allow parallel development within or across teams, and to lower maintenance.
I prefer to use constructor injection
and have often observed that I need
about 5 or more objects to be injected
in the constructor.
As you already noted yourself, having many dependencies could be caused by not adhering to the SRP. What you can do however, is grouping common dependencies with there logic into an aggregate service and inject that into consumers. Also see Mark Seemann's article about Aggregate Services.
Objects that are true singletons like
application configuration or those
small util classes, do you inject
them?
I am personally not a fan of the way Ayende proposes it. This is an Ambient Context, which is a specific sort of service locator construct. Doing this hides the dependency, because classes can call that static class without you having to inject it. Explicitly injecting it makes it much clearer that you need to unit test time. Besides that, it makes it hard to write tests for frameworks such as MSTest who tend to run tests in parallel. Without any countermeasures, it makes your tests very unreliable. A better solution -for the DateTime.Now
example- is to have an IClock
interface, as is suggested here. As you can see, that answer scores much higher than Ayende approach, that is shown in the same SO question.
Common objects such as logging, that
are used in almost every object,
should they be injected?
I inject them in my code, because that makes the dependencies clear. Note however, that in my code I still hardly ever have to inject a logger. Think hard about every line you want to log and it isn't really a failure (or a cross-cutting concern that should be placed elsewhere). I usually throw an exception when something happened that I didn't expect. It allows me to find bugs fast. Or to put it in other words: Don't filter, but fail fast. And please ask yourself: "Do I log too much?"
I hope this helps.