最新ニュースのリストを含むウィジェットがあります。ウィジェット出力のみをキャッシュするにはどうすればよいですか? OutputCache モジュールはページ全体と匿名ユーザーをキャッシュしますが、実際には 1 つの形状出力のみをキャッシュする必要があります。ここでどのような解決策が考えられますか?
2 に答える
Shape
オブジェクト自体をキャッシュすることはお勧めできませんが、 から HTML 出力をキャプチャしてキャッシュすることはできますShape
。
すべての果樹園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()、およびシェイプ テンプレートで実行するその他の副作用などは再生されません。独自のスタイルシートを必要とするテンプレートをキャッシュしようとしたため、これは実際に私を苦しめましたが、スタイルシートは最初に読み込まれるだけでした。
Orchard は CacheManager と呼ばれるサービスを提供しています。これは素晴らしくてクールで、キャッシングを非常に簡単にします。ドキュメントに記載されていますが、その使用方法について特に役立つ説明ではありません ( http://docs.orchardproject.net/Documentation/Caching )。例を見るのに最適な場所は、Orchard コア コードと、Favicon や twitter ウィジェットなどのサード パーティ モジュールです (それらすべてが望ましいと思われます)。
幸いなことに、他の素敵な人々があなたのために果樹園のコードを検索し、それについて素敵な小さなブログ記事を書いてくれました。LatestTwitter ウィジェットの開発者は、http://blog.maartenballiauw.be/post/2011/01/21/Writing-an-Orchard-widget-LatestTwitter.aspx というすばらしい投稿を書きました。NogginBox の Richard もそうでした: 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