我有一个包含最新消息列表的小部件,如何仅缓存小部件输出? OutputCache模块缓存整个页面和匿名用户,但实际上我只需要缓存一个形状输出。 什么解决方案可以在这里?
答案 0 :(得分:4)
缓存Shape
对象本身并不是一个好主意,但是你可以从Shape
捕获HTML输出并缓存它。
每个Orchard Shape
都有一个名为Metadata
的对应对象。此对象包含一些事件处理程序,这些事件处理程序可以在显示Shape
时显示,也可以在显示后运行。通过使用这些事件处理程序,可以在第一次调用时将Shape
的输出缓存到驱动程序。然后,为了将来调用驱动程序,我们可以显示输出的缓存副本,而不是运行驱动程序或模板渲染的昂贵部分。
示例:
using System.Web;
using DemoModule.Models;
using Orchard.Caching;
using Orchard.ContentManagement.Drivers;
using Orchard.DisplayManagement.Shapes;
namespace DemoModule.Drivers {
public class MyWidgetPartDriver : ContentPartDriver<MyWidgetPart> {
private readonly ICacheManager _cacheManager;
private readonly ISignals _signals;
public MyWidgetPartDriver(
ICacheManager cacheManager,
ISignals signals
) {
_cacheManager = cacheManager;
_signals = signals;
}
public class CachedOutput {
public IHtmlString Output { get; set; }
}
protected override DriverResult Display(MyWidgetPart part, string displayType, dynamic shapeHelper) {
return ContentShape("Parts_MyWidget", () => {
// The cache key. Build it using whatever is needed to differentiate the output.
var cacheKey = /* e.g. */ string.Format("MyWidget-{0}", part.Id);
// Standard Orchard cache manager. Notice we get this object by reference,
// so we can write to its field to save our cached HTML output.
var cachedOutput = _cacheManager.Get(cacheKey, ctx => {
// Use whatever signals are needed to invalidate the cache.
_signals.When(/* e.g. */ "ExpireCache");
return new CachedOutput();
});
dynamic shape;
if (cachedOutput.Output == null) {
// Output has not yet been cached, so we are going to build the shape normally
// and then cache the output.
/*
... Do normal (potentially expensive) things (call DBs, call services, etc.)
to prep shape ...
*/
// Create shape object.
shape = shapeHelper.Parts_MyWidget(/*...*/);
// Hook up an event handler such that after rendering the (potentially expensive)
// shape template, we capture the output to the cached output object.
((ShapeMetadata) shape.Metadata).OnDisplayed(displayed => cachedOutput.Output = displayed.ChildContent);
} else {
// Found cached output, so simply output it instead of building
// the shape normally.
// This is a dummy shape, the name doesn't matter.
shape = shapeHelper.CachedShape();
// Hook up an event handler to fill the output of this shape with the cached output.
((ShapeMetadata)shape.Metadata).OnDisplaying(displaying => displaying.ChildContent = cachedOutput.Output);
// Replacing the ChildContent of the displaying context will cause the display manager
// to simply use that HTML output and skip template rendering.
}
return shape;
});
}
}
}
编辑: 请注意,这只会缓存从形状输出生成的HTML。诸如Script.Require(),Capture()以及您在形状模板中执行的其他副作用之类的内容将无法播放。这实际上是因为我试图缓存一个需要自己的样式表的模板,但样式表只会在第一次出现。
答案 1 :(得分:1)
Orchard提供了一个名为CacheManager的服务,它非常棒且很酷,并且使缓存非常容易。它在文档中提到,但它并不是如何使用它的特别有用的描述(http://docs.orchardproject.net/Documentation/Caching)。查看示例的最佳位置是Orchard核心代码和第三方模块,如Favicon和twitter小部件(所有人都希望如此)。
幸运的是,其他好人已经为你寻找orchards代码并编写了很好的小博客文章。 LatestTwitter小部件的开发人员撰写了一篇简洁的文章:http://blog.maartenballiauw.be/post/2011/01/21/Writing-an-Orchard-widget-LatestTwitter.aspx。 NogginBox的理查德也是如此:http://www.nogginbox.co.uk/blog/orchard-caching-by-time。当然,Bertrand也有关于这个主题的有用帖子:http://weblogs.asp.net/bleroy/archive/2011/02/16/caching-items-in-orchard.aspx