diff --git a/README.md b/README.md
index 646dcab3..258932e0 100644
--- a/README.md
+++ b/README.md
@@ -120,7 +120,7 @@ The API is designed around the idea that you do not have the templates sitting a
(while you can do that as seen above).
The main interface to provide RazorEngine with templates is the `ITemplateManager` interface.
You should either pick one of the available implementations or write your own.
-See [the documentation](http://antaris.github.io/RazorEngine/TemplateManager.html) for details
+See [TemplateManager and Caching documentation](http://antaris.github.io/RazorEngine/TemplateManager.html) for details.
## Temporary files
diff --git a/doc/Caching.md b/doc/Caching.md
index 708155c3..2872db7e 100644
--- a/doc/Caching.md
+++ b/doc/Caching.md
@@ -1,138 +1,4 @@
# RazorEngine Caching API
-RazorEngine provides a robust caching layer out of the box which should suite most use-cases.
-If you use "Compile" on application startup and "Run" on every use of the application you can be
-sure that caching works (as "Run" would throw if there is no cached template).
-If you want "lazy"-compilation of the templates you would just use "RunCompile".
-
-However if you need some custom features (like caching across multiple runs of the application, or cleanup of compiled templates)
-you want to run your own caching implementation.
-All you need to do is implement the ICachingProvider and set an instance of your implementation in the configuration.
-As starting point you can use the DefaultCachingProvider (latest code is in the repository):
-
-```csharp
-config.CachingProvider = new DefaultCachingProvider();
-
-///
-/// The default caching provider (See ).
-/// This implementation does a very simple in-memory caching.
-/// It can handle when the same template is used with multiple model-types.
-///
-public class DefaultCachingProvider : ICachingProvider
-{
- private readonly ConcurrentDictionary> _cache =
- new ConcurrentDictionary>();
-
- private readonly TypeLoader _loader;
- private readonly ConcurrentBag _assemblies = new ConcurrentBag();
-
- ///
- /// Initializes a new instance of the class.
- ///
- public DefaultCachingProvider()
- {
- _loader = new TypeLoader(AppDomain.CurrentDomain, _assemblies);
- }
-
- ///
- /// The manages . See
- ///
- public TypeLoader TypeLoader
- {
- get
- {
- return _loader;
- }
- }
-
- ///
- /// Get the key used within a dictionary for a modelType.
- ///
- public static Type GetModelTypeKey(Type modelType)
- {
- if (modelType == null ||
- typeof(System.Dynamic.IDynamicMetaObjectProvider).IsAssignableFrom(modelType))
- {
- return typeof(System.Dynamic.DynamicObject);
- }
- return modelType;
- }
-
- private void CacheTemplateHelper(ICompiledTemplate template, ITemplateKey templateKey, Type modelTypeKey)
- {
- var uniqueKey = templateKey.GetUniqueKeyString();
- _cache.AddOrUpdate(uniqueKey, key =>
- {
- // new item added
- _assemblies.Add(template.TemplateAssembly);
- var dict = new ConcurrentDictionary();
- dict.AddOrUpdate(modelTypeKey, template, (t, old) => template);
- return dict;
- }, (key, dict) =>
- {
- dict.AddOrUpdate(modelTypeKey, t =>
- {
- // new item added (template was not compiled with the given type).
- _assemblies.Add(template.TemplateAssembly);
- return template;
- }, (t, old) =>
- {
- // item was already added before
- return template;
- });
- return dict;
- });
- }
-
- ///
- /// Caches a template. See .
- ///
- ///
- ///
- public void CacheTemplate(ICompiledTemplate template, ITemplateKey templateKey)
- {
- var modelTypeKey = GetModelTypeKey(template.ModelType);
- CacheTemplateHelper(template, templateKey, modelTypeKey);
- var typeArgs = template.TemplateType.BaseType.GetGenericArguments();
- if (typeArgs.Length > 0)
- {
- var alternativeKey = GetModelTypeKey(typeArgs[0]);
- if (alternativeKey != modelTypeKey)
- {
- // could be a template with an @model directive.
- CacheTemplateHelper(template, templateKey, typeArgs[0]);
- }
- }
- }
-
- ///
- /// Try to retrieve a template from the cache. See .
- ///
- ///
- ///
- ///
- ///
- public bool TryRetrieveTemplate(ITemplateKey templateKey, Type modelType, out ICompiledTemplate compiledTemplate)
- {
- compiledTemplate = null;
- var uniqueKey = templateKey.GetUniqueKeyString();
- var modelTypeKey = GetModelTypeKey(modelType);
- ConcurrentDictionary dict;
- if (!_cache.TryGetValue(uniqueKey, out dict))
- {
- return false;
- }
- return dict.TryGetValue(modelTypeKey, out compiledTemplate);
- }
-
- ///
- /// Dispose the instance.
- ///
- public void Dispose()
- {
- _loader.Dispose();
- }
-}
-```
-
+Moved to [TemplateManager.html](http://antaris.github.io/RazorEngine/TemplateManager.html)
\ No newline at end of file
diff --git a/doc/TemplateManager.md b/doc/TemplateManager.md
index 36e10a16..13dc0ba4 100644
--- a/doc/TemplateManager.md
+++ b/doc/TemplateManager.md
@@ -1,6 +1,7 @@
-# `TemplateManager` and `ICachingProvider`
+# ITemplateManager and ICachingProvider
-This section explains how `TemplateManager` work, which ones are available by default and how to write your own.
+This section explains how `ITemplateManager` and `ICachingProvider` work and play together,
+which implementations are available by default and how to write your own.
## Template resolving
@@ -33,12 +34,13 @@ The `GetKey` step enables a `TemplateManager` to add customized data to the key
Note that this introduces a memory leak to your application, so only use this is you have an AppDomain recycle strategy in place
or for debugging purposes.
- > Mono doesn't always detect changes, if you have problems report a bug to mono and try to use
- `Environment.SetEnvironmentVariable("MONO_MANAGED_WATCHER", "enabled");`
- Related:
- http://stackoverflow.com/questions/16859372/why-doesnt-the-servicestack-razor-filesystemwatcher-work-on-mono-mac-os-x
- http://stackoverflow.com/questions/16519000/filesystemwatcher-under-mono-watching-subdirs
- ``
+
+ > Mono doesn't always detect changes, if you have problems report a bug to mono and try to use
+ > `Environment.SetEnvironmentVariable("MONO_MANAGED_WATCHER", "enabled");`
+ > Related:
+ > http://stackoverflow.com/questions/16859372/why-doesnt-the-servicestack-razor-filesystemwatcher-work-on-mono-mac-os-x
+ > http://stackoverflow.com/questions/16519000/filesystemwatcher-under-mono-watching-subdirs
+ > ``
## Available CachingProviders
@@ -47,7 +49,9 @@ The `GetKey` step enables a `TemplateManager` to add customized data to the key
Note that invalidating cached templates doesn't actually free the memory (loaded assemblies), so only use this
for debugging purposes or if you have an `AppDomain` recycle strategy in place.
-## Writing your own
+## Writing your own `ITemplateManager`
+
+If the above implementations don't fit your needs you can roll your own:
```csharp
config.TemplateManager = new MyTemplateManager();
@@ -69,15 +73,157 @@ public class MyTemplateManager : ITemplateManager
// context or the resolveType you need your own implementation here!
// Otherwise you can just use NameOnlyTemplateKey.
return new NameOnlyTemplateKey(name, resolveType, context);
+ // template is specified by full path
+ //return new FullPathTemplateKey(name, fullPath, resolveType, context);
}
public void AddDynamic(ITemplateKey key, ITemplateSource source)
{
- // You can disable dynamic templates completely, but
- // then all convenience methods (Compile and RunCompile) with
+ // You can disable dynamic templates completely.
+ // This just means all convenience methods (Compile and RunCompile) with
// a TemplateSource will no longer work (they are not really needed anyway).
throw new NotImplementedException("dynamic templates are not supported!");
}
}
```
+Contributing your implementation back to RazorEngine is highly appreciated.
+
+## Writing your own `ICachingProvider`
+
+RazorEngine provides a robust caching layer out of the box which should suite most use-cases.
+If you use "Compile" on application startup and "Run" on every use of the application you can be
+sure that caching works (as "Run" would throw if there is no cached template).
+If you want "lazy"-compilation of the templates you would just use "RunCompile".
+
+However if you need some custom features (like caching across multiple runs of the application)
+you want to run your own caching implementation.
+All you need to do is implement the `ICachingProvider` interface and set an instance of your implementation in the configuration.
+As starting point you can use the DefaultCachingProvider (latest code is in the repository):
+
+```csharp
+config.CachingProvider = new DefaultCachingProvider();
+
+///
+/// The default caching provider (See ).
+/// This implementation does a very simple in-memory caching.
+/// It can handle when the same template is used with multiple model-types.
+///
+public class DefaultCachingProvider : ICachingProvider
+{
+ private readonly ConcurrentDictionary> _cache =
+ new ConcurrentDictionary>();
+
+ private readonly TypeLoader _loader;
+ private readonly ConcurrentBag _assemblies = new ConcurrentBag();
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public DefaultCachingProvider()
+ {
+ _loader = new TypeLoader(AppDomain.CurrentDomain, _assemblies);
+ }
+
+ ///
+ /// The manages . See
+ ///
+ public TypeLoader TypeLoader
+ {
+ get
+ {
+ return _loader;
+ }
+ }
+
+ ///
+ /// Get the key used within a dictionary for a modelType.
+ ///
+ public static Type GetModelTypeKey(Type modelType)
+ {
+ if (modelType == null ||
+ typeof(System.Dynamic.IDynamicMetaObjectProvider).IsAssignableFrom(modelType))
+ {
+ return typeof(System.Dynamic.DynamicObject);
+ }
+ return modelType;
+ }
+
+ private void CacheTemplateHelper(ICompiledTemplate template, ITemplateKey templateKey, Type modelTypeKey)
+ {
+ var uniqueKey = templateKey.GetUniqueKeyString();
+ _cache.AddOrUpdate(uniqueKey, key =>
+ {
+ // new item added
+ _assemblies.Add(template.TemplateAssembly);
+ var dict = new ConcurrentDictionary();
+ dict.AddOrUpdate(modelTypeKey, template, (t, old) => template);
+ return dict;
+ }, (key, dict) =>
+ {
+ dict.AddOrUpdate(modelTypeKey, t =>
+ {
+ // new item added (template was not compiled with the given type).
+ _assemblies.Add(template.TemplateAssembly);
+ return template;
+ }, (t, old) =>
+ {
+ // item was already added before
+ return template;
+ });
+ return dict;
+ });
+ }
+
+ ///
+ /// Caches a template. See .
+ ///
+ ///
+ ///
+ public void CacheTemplate(ICompiledTemplate template, ITemplateKey templateKey)
+ {
+ var modelTypeKey = GetModelTypeKey(template.ModelType);
+ CacheTemplateHelper(template, templateKey, modelTypeKey);
+ var typeArgs = template.TemplateType.BaseType.GetGenericArguments();
+ if (typeArgs.Length > 0)
+ {
+ var alternativeKey = GetModelTypeKey(typeArgs[0]);
+ if (alternativeKey != modelTypeKey)
+ {
+ // could be a template with an @model directive.
+ CacheTemplateHelper(template, templateKey, typeArgs[0]);
+ }
+ }
+ }
+
+ ///
+ /// Try to retrieve a template from the cache. See .
+ ///
+ ///
+ ///
+ ///
+ ///
+ public bool TryRetrieveTemplate(ITemplateKey templateKey, Type modelType, out ICompiledTemplate compiledTemplate)
+ {
+ compiledTemplate = null;
+ var uniqueKey = templateKey.GetUniqueKeyString();
+ var modelTypeKey = GetModelTypeKey(modelType);
+ ConcurrentDictionary dict;
+ if (!_cache.TryGetValue(uniqueKey, out dict))
+ {
+ return false;
+ }
+ return dict.TryGetValue(modelTypeKey, out compiledTemplate);
+ }
+
+ ///
+ /// Dispose the instance.
+ ///
+ public void Dispose()
+ {
+ _loader.Dispose();
+ }
+}
+```
+
+Contributing your implementation back to RazorEngine is highly appreciated.
\ No newline at end of file
diff --git a/doc/templates/template.cshtml b/doc/templates/template.cshtml
index 5f2ace5d..3c50703f 100644
--- a/doc/templates/template.cshtml
+++ b/doc/templates/template.cshtml
@@ -61,7 +61,7 @@
Encoding Values in Razor
Reference Resolver
Isolation and Sandboxing
- Caching API
+ TemplateManager and Caching
Development Intro
Upgrading Guide (3.5.0)
Release Notes