cache asset files with the `Dassets[]` asset lookup method

With the addition of the source cache and combinations, creating
AssetFile instances is not a trivial/fast as it originally was.
This is especially true for large/complex combinations.  This
adds a cache for the asset file lookups so that the asset files
are not continually rebuilt each time they are accessed.

This preserves the ability to alter existing asset files without
needing to reload.  However, if you make a change to any combinations,
you will need to reload Dassets to clear this cache and see you
changes.
cache asset file object on access

Building asset files has become a non-trivial operation with the
addition of source proxies and combinations.  This changes the
`Dassets[]` method to cache the asset file objects so they don't
have to be rebuilt each time they are accessed.

This can provide a significant speed boost when using large/complex
combinations as an asset file may be accessed multiple times in any
given request (template rendering, middleware serving, etc).