一種方法是使用緩存interceptor。如果您使用依賴注入容器(如Unity或Windsor)來管理依賴關係,那麼您可以從中獲得一些附加值。
假設圖像下載你有這個接口和實現:
public interface IImageDownloader
{
BitmapImage GetImage(Uri uri);
}
public class ImageDownloader : IImageDownloader
{
public BitmapImage GetImage(Uri uri)
{
// Your implementation
return null;
}
}
你可以告訴你的容器(使用Unity作爲一個例子)創建的ImageDownloader
實例時,你需要一個IImageDownloader
。
container.RegisterType<IImageDownloader, ImageDownloader>();
到目前爲止,這與緩存無關。它只是使用依賴注入,以便其他類依賴於接口(IImageDownloader
)而不是具體的類。
但是,您可以獲得攔截的額外好處。容器可以「圍繞」課堂上的其他行爲。下面是基於this documentation一個例子:
public class ImageDownloadCacheInterceptionBehavior : IInterceptionBehavior
{
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Uri uriArgument = (input.Arguments.Count > 0) ? input.Arguments[0] as Uri : null;
if (uriArgument == null)
{
return getNext()(input, getNext);
}
var key = CreateKey(uriArgument);
using (var cache = MemoryCache.Default)
{
var cached = cache[key] as BitmapImage;
if (cached == null)
{
cached = getNext()(input, getNext).ReturnValue as BitmapImage;
if(cached!=null)
cache.Add(key, cached, DateTimeOffset.Now.AddHours(1));
}
return input.CreateMethodReturn(cached);
}
}
private string CreateKey(Uri uri)
{
return "ImageCache" + uri;
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public bool WillExecute => true;
}
現在就來告訴團結了使用的攔截:
container.AddNewExtension<Interception>();
container.RegisterType<IImageDownloader, ImageDownloader>(
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<ImageDownloadCacheInterceptionBehavior>()
);
這只是典型的緩存行爲。它從Uri
創建緩存密鑰,然後如果該項目在緩存中,則返回該緩存密鑰。如果不是,它會繼續調用正在調用的方法,並且在完成後它將返回值放入緩存中,然後再返回。
從所有這些工作中獲得的主要好處是緩存行爲不在ImageDownloader
類中。該課程有一項工作要做 - 下載一張圖片 - 因此它測試簡單且容易。如果你不得不把緩存放在那個方法中,那麼它會更長更復雜。攔截允許您將行爲添加到不屬於的類中,該類在中。
例如,如果您想在某些情況下緩存但不在其他情況下如何緩存?您可能最終會在您的方法中使用bool shouldCache
或TimeSpan cacheDuration
等參數編寫奇怪的重載。
這樣你仍然有你的緩存行爲的複雜性,但你可以保持它的獨立性。
另一個應用程序是異常處理。如果每個班級都有自己的try/catch/log
方法,這可能會很痛苦,特別是如果有一天您的記錄方法發生變化。但相反,您可以將這個異常處理掉,讓您的課程自行完成。攔截器可以捕獲異常並將其記錄下來。
所有這一切只是好像很多額外的工作,當你開始使用它,你得到它的工作。但是,一旦你克服了這個麻煩,它可以創造奇蹟,幫助管理你的代碼的複雜性。
最初的挑戰只是學習如何在給定類型的應用程序中使用依賴注入容器。 Here's an article在WPF應用程序中進行設置。
當您看到有多少框架(ASP.NET Core,Angular)宣告內置依賴注入或與依賴注入的兼容性時,模式的值就會變得明顯。
如何緩存BitmapImage或BitmapFrame實例的簡單綁定轉換器(從字符串/ Uri到ImageSource)? – Clemens