TemplateEngine.cs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6. using Nancy.ViewEngines.Razor;
  7. using Nancy.ViewEngines;
  8. using Nancy.Localization;
  9. using Nancy;
  10. namespace CB.Common
  11. {
  12. public class TemplateEngine
  13. {
  14. private readonly RazorViewEngine engine;
  15. //private volatile IRenderContext renderContext;//要么增加volatile,目前选择在代码段内设置
  16. private readonly IRazorConfiguration configuration;
  17. private readonly FileSystemViewLocationProvider fileSystemViewLocationProvider;
  18. private readonly IRootPathProvider rootPathProvider;
  19. private readonly ITextResource textResource;
  20. private readonly DiagnosticsViewResolver viewResolver;
  21. //private readonly System.Threading.ThreadLocal<IRenderContext> threadLocal;
  22. private readonly Func<IRenderContext> createContext;
  23. private TemplateEngine()
  24. {
  25. this.configuration = new CBRazorConfiguration();//new DefaultRazorConfiguration();
  26. this.textResource = new ResourceBasedTextResource(new DefaultAssemblyProvider());//new ResourceBasedTextResource(new ResourceAssemblyProvider());
  27. this.engine = new RazorViewEngine(this.configuration, this.textResource);//new RazorViewEngine(configuration);//
  28. this.rootPathProvider = new CPWapRootPathProvider();//new DefaultRootPathProvider();
  29. this.fileSystemViewLocationProvider = new FileSystemViewLocationProvider(this.rootPathProvider,
  30. new DefaultFileSystemReader());
  31. IViewCache cache = new WapViewCache();//DefaultViewCache();
  32. //this.viewCache = new DefaultViewCache();
  33. this.viewResolver = new DiagnosticsViewResolver(fileSystemViewLocationProvider);
  34. //this.renderContext =
  35. // new DefaultRenderContextFactory(cache, viewResolver).GetRenderContext(new ViewLocationContext()
  36. // {
  37. // Context = new NancyContext()
  38. // });
  39. createContext = () =>
  40. {
  41. return new DefaultRenderContextFactory(cache, viewResolver).GetRenderContext(new ViewLocationContext()
  42. {
  43. Context = new NancyContext()
  44. });
  45. //return new DefaultRenderContext(viewResolver, cache, textResource, new ViewLocationContext()
  46. //{
  47. // Context = new NancyContext()
  48. //});
  49. };
  50. //threadLocal = new System.Threading.ThreadLocal<IRenderContext>(createContext);
  51. }
  52. internal class CPWapRootPathProvider : IRootPathProvider
  53. {
  54. public string GetRootPath()
  55. {
  56. return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "templates", "rzs");
  57. }
  58. }
  59. internal class DiagnosticsViewResolver : IViewResolver
  60. {
  61. private readonly FileSystemViewLocationProvider fileSystemViewLocationProvider;
  62. public DiagnosticsViewResolver(FileSystemViewLocationProvider fileSystemViewLocationProvider)
  63. {
  64. this.fileSystemViewLocationProvider = fileSystemViewLocationProvider;
  65. }
  66. public ViewLocationResult FindView(string viewName)
  67. {
  68. if (viewName.EndsWith("cshtml"))
  69. viewName = viewName.Substring(0, viewName.Length - 7);
  70. if (viewName.EndsWith("shtml"))
  71. viewName = viewName.Substring(0, viewName.Length - 6);
  72. var location =
  73. this.fileSystemViewLocationProvider.GetLocatedViews(new[] {"cshtml", "vbhtml"})
  74. .First(r => r.Name.ToLower() == viewName.ToLower());
  75. return location;
  76. }
  77. public ViewLocationResult GetViewLocation(string viewName, dynamic model,
  78. ViewLocationContext viewLocationContext)
  79. {
  80. return FindView(viewName);
  81. }
  82. }
  83. //for testing,can use web.config to config
  84. /// <summary>
  85. /// razor配置类
  86. /// </summary>
  87. /// <remarks>
  88. /// <razor disableAutoIncludeModelNamespace="false">
  89. /// <assemblies>
  90. /// <add assembly="System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  91. /// <add assembly="Nancy.Hosting.Aspnet" />
  92. /// </assemblies>
  93. /// <namespaces>
  94. /// <add namespace="System.Xml" />
  95. /// </namespaces>
  96. /// </razor>
  97. /// </remarks>
  98. [Obsolete("使用DefaultRazorConfiguration类,可以在config中进行配置")]
  99. public class CBRazorConfiguration : IRazorConfiguration
  100. {
  101. public bool AutoIncludeModelNamespace
  102. {
  103. get { return false; }
  104. }
  105. public IEnumerable<string> GetAssemblyNames()
  106. {
  107. return new string[] { "CB.Entity", "CB.Common", "CB.Wap", "CB.Data", "CB.Cache", "CB.Interface", "CB.Framework" };
  108. }
  109. public IEnumerable<string> GetDefaultNamespaces()
  110. {
  111. return new string[] { "CB.Entity", "CB.Common", "CB.Wap", "CB.Data", "CB.Cache", "CB.Interface", "CB.Framework" };
  112. }
  113. }
  114. private volatile static TemplateEngine _templateEngine;
  115. //static TemplateEngine()
  116. //{
  117. // _templateEngine = new TemplateEngine();
  118. //}
  119. public static TemplateEngine Template
  120. {
  121. get
  122. {
  123. return new TemplateEngine();
  124. /*
  125. if (_templateEngine == null)
  126. {
  127. _templateEngine = new TemplateEngine();
  128. //System.Threading.Interlocked.CompareExchange<TemplateEngine>(ref _templateEngine, new TemplateEngine(), null);
  129. }
  130. return _templateEngine;//*/
  131. }
  132. }
  133. public Action<Stream> ExecuteTemplate(string viewName, object model, IDictionary<string, object> viewbag)
  134. {
  135. var renderContext = createContext();//threadLocal.Value;
  136. var hash = ((DynamicDictionary)renderContext.Context.ViewBag);
  137. hash.Clear();
  138. if (viewbag != null && viewbag.Count > 0)
  139. {
  140. foreach (var kv in viewbag)
  141. {
  142. hash.Add(kv);
  143. }
  144. }
  145. var location = viewResolver.FindView(viewName);
  146. if (location == null)
  147. return null;
  148. var resp = this.engine.RenderView(location, model, renderContext);
  149. return resp.Contents;
  150. }
  151. public StringBuilder GetTemplateContent(string viewName, object model, IDictionary<string, object> viewbag)
  152. {
  153. var ms = new MemoryStream();
  154. var action = ExecuteTemplate(viewName, model, viewbag);
  155. if (action == null) return null;
  156. action.Invoke(ms);
  157. ms.Position = 0;
  158. var sb = new StringBuilder();
  159. using (var reader = new StreamReader(ms))
  160. {
  161. while (reader.Peek() > -1)
  162. {
  163. sb.Append(reader.ReadLine());
  164. }
  165. }
  166. return sb;
  167. }
  168. //private static readonly object locker = new object();
  169. //private readonly System.Threading.SpinLock spinlock = new System.Threading.SpinLock();
  170. //public StringBuilder GetTemplateContent(string viewName, object model, IDictionary<string, object> viewbag)
  171. //{
  172. // var t = System.Threading.Tasks.Task.Factory.StartNew(() =>
  173. // {
  174. // bool lockTaken = false;
  175. // try
  176. // {
  177. // spinlock.Enter(ref lockTaken);
  178. // return GetTemplateContent1(viewName, model, viewbag);
  179. // }
  180. // finally
  181. // {
  182. // if (lockTaken) spinlock.Exit(false);
  183. // }
  184. // });
  185. // System.Threading.Tasks.Task.WaitAny(new System.Threading.Tasks.Task[] { t }, 1000);
  186. // return t.Result;
  187. //}
  188. }
  189. public class WapViewCache : IViewCache
  190. {
  191. private readonly System.Web.Caching.Cache webCache = System.Web.HttpRuntime.Cache;
  192. const string PrefixKey = "_Razor_Template_p_";
  193. readonly object objLocker = new object();
  194. public TCompiledView GetOrAdd<TCompiledView>(ViewLocationResult viewLocationResult, Func<ViewLocationResult, TCompiledView> valueFactory)
  195. {
  196. if (StaticConfiguration.DisableCaches)
  197. {
  198. return valueFactory(viewLocationResult);
  199. }
  200. var key = PrefixKey + viewLocationResult.Name;
  201. object o = webCache.Get(key);
  202. if (o == null)
  203. {
  204. //lock (objLocker)
  205. //{
  206. // if (o == null)
  207. // {
  208. // }
  209. //}
  210. o = valueFactory(viewLocationResult);
  211. var nextSecondDay = DateTime.Now.AddDays(1);
  212. nextSecondDay = DateTime.Parse(nextSecondDay.ToString("yyyy-MM-dd") + " 01:00:00");
  213. webCache.Insert(key, o, null, System.DateTime.Now.AddHours(36), TimeSpan.Zero);
  214. }
  215. return (TCompiledView)o;
  216. }
  217. public void Remove(ViewLocationResult viewLocationResult)
  218. {
  219. if (StaticConfiguration.DisableCaches)
  220. return;
  221. var key = PrefixKey + viewLocationResult.Name;
  222. object o = webCache.Get(key);
  223. if (o != null)
  224. webCache.Remove(key);
  225. return;
  226. }
  227. }
  228. }