在Nancy中,給我們的網站換個自定義的圖標。
當我們在做一個網站時,可能經常會有這樣一個需求,要給我們做的網站添加一個自定義的圖標。
在Nancy中,預設是的下麵這樣
一個妹子的頭像,其實也是挺好看的!!
那麼當我們想要替換這個預設的,應該要怎麼做呢?
下麵就來看看具體的實現
首先,準備一張名為 favicon.ico或 favicon.png 圖片
這裡有兩種實現方法提供參考
方法一:替換預設的圖標(IRootPathProvider的實現)
如果我們是使用預設的IRootPathProvider的實現,這個時候,我們直接添加圖片在我們的項目根目錄即可
Nancy會去搜索這個預設的RootPath的favicon資源,它找到的第一個就將會是我們網站的圖標。
效果如下:
有時候,預設的不一定是最好的,所以我們可以
自己去實現IRootPathProvider這個介面,但一個項目中,只能有一個實現(除了預設的)
具體如下
1 public class CustomRootPathProvider : IRootPathProvider 2 { 3 public string GetRootPath() 4 { 5 return AppDomain.CurrentDomain.GetData(".appPath").ToString(); 6 } 7 }
其中,GetRootPath返回的是絕對路徑!!
這個路徑可以用你能想到的任何方式得到!
然後,我們需要在“引導程式”中做點事
1 protected override IRootPathProvider RootPathProvider 2 { 3 get { return new CustomRootPathProvider(); } 4 }
這樣做是比較保險的一種做法(不需要特地將我們的圖片資源設置為嵌入的資源)
方法二:使用嵌入的圖標(Override FavIcon)
這種方法需要我們去重寫 FacIcon這個方法
1 protected override byte[] FavIcon 2 { 3 get { return this.favicon ?? (this.favicon = LoadFavIcon()); } 4 } 5 private byte[] LoadFavIcon() 6 { 7 using (var resourceStream = GetType().Assembly.GetManifestResourceStream("NancyFavIconDemo.favicon.ico")) 8 { 9 var tempFavicon = new byte[resourceStream.Length]; 10 resourceStream.Read(tempFavicon, 0, (int)resourceStream.Length); 11 return tempFavicon; 12 } 13 }
其中,GetMainifestResourceStream的參數是“程式集名稱.資源名稱”(NancyFavIconDemo是我這個Demo的程式集名稱,favicon.ico是我在根目錄的一個圖片)
還有重要的一步是
將我們的圖片屬性中的Build Action設置為 Embedded Resource(嵌入的資源)
具體原因我們可以參考Assembly.GetManifestResourceStream Method (String)裡面的Remark
A manifest resource is a resource (such as an image file) that is embedded in the assembly at compile time.
此時,我們同樣可以看到相同的效果
如果 我們沒有設置為嵌入的資源,那麼我們的resourceStream對象將一直為空 下麵我們來看看Nancy這一塊內容的內部實現 關於favicon的實現就是在FavIconApplicationStartup.cs裡面 來看看它的描述 就像前面說的,它會去找favicon,找到就用找到的,沒找到就用預設的。 裡面有一個帶IRootPathProvider參數構造函數,可以簡單理解為指定要搜索的範圍。1 /// <summary> 2 /// Initializes a new instance of the <see cref="FavIconApplicationStartup"/> class, with the 3 /// provided <see cref="IRootPathProvider"/> instance. 4 /// </summary> 5 /// <param name="rootPathProvider">The <see cref="IRootPathProvider"/> that should be used to scan for a favicon.</param> 6 public FavIconApplicationStartup(IRootPathProvider rootPathProvider) 7 { 8 FavIconApplicationStartup.rootPathProvider = rootPathProvider; 9 }
下麵是預設的圖標實現方法,我們override的實現和它的基本一致!!
1 private static byte[] ExtractDefaultIcon() 2 { 3 var resourceStream = 4 typeof(INancyEngine).Assembly.GetManifestResourceStream("Nancy.favicon.ico"); 5 6 if (resourceStream == null) 7 { 8 return null; 9 } 10 11 var result = 12 new byte[resourceStream.Length]; 13 14 resourceStream.Read(result, 0, (int)resourceStream.Length); 15 16 return result; 17 }
預設圖標在ErrorPipeline.cs和FormatterExtensions.cs之間(不細心去看,壓根就看不見)
裡面還有一個“搜索”圖標的方法1 private static byte[] LocateIconOnFileSystem() 2 { 3 if (rootPathProvider == null) 4 { 5 return null; 6 } 7 8 var extensions = new[] { "ico", "png" }; 9 10 var locatedFavIcon = extensions.SelectMany(EnumerateFiles).FirstOrDefault(); 11 if (locatedFavIcon == null) 12 { 13 return null; 14 } 15 16 try 17 { 18 return File.ReadAllBytes(locatedFavIcon); 19 } 20 catch (Exception e) 21 { 22 if (!StaticConfiguration.DisableErrorTraces) 23 { 24 throw new InvalidDataException("Unable to load favicon", e); 25 } 26 27 return null; 28 } 29 }
我們可以發現,我們用的尾碼可以是.ico和.png。