如何为内容部分(例如窗口小部件)实现输出缓存?

时间:2013-10-28 15:15:06

标签: orchardcms

我有一个包含最新消息列表的小部件,如何仅缓存小部件输出? OutputCache模块缓存整个页面和匿名用户,但实际上我只需要缓存一个形状输出。 什么解决方案可以在这里?

2 个答案:

答案 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