緣起:
我們公司的程式有個專案,它是一個 DLL
專案,用來管理一些前後台會用到的 js、css、image 資源,只要 build
完,它就變成一個 DLL
檔,資源都包含在裡面。如果那個專案裡的檔案有被新增或修改,到時要更新的話就只要搬
DLL 檔去覆蓋就好,非常的方便。
把東西都包進 DLL 裡,然後再寫個 class 當個介面來存取 DLL
檔的資源,感覺是個很實用的做法,所以想學起來。
這篇想要寫個測試的小程式來達到跟我們專案一樣的功能,從
DLL 裡把檔案給取出。
新增 DLL 專案並引用:
我是先建立一個 Console 的方案,然後再加入一個 DLL
的專案。
右鍵點方案 -> 加入 -> 新增專案 |
選擇 "類別庫(.NET Framework)",然後點"下一步" |
為專案命名,最後按下"建立"就完成了 |
哦對,你 Console 跟 DLL 專案的架構是要一樣的,我有次兩個選不一樣,它在 build 時就不給我過。
它專案預設會有個 Class1 的 cs
檔,我們不需要,所以把它給砍了,建立自己的 cs 檔,叫
"MyManager",然後改成這樣
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyLibrary
{
public class MyManager
{
public static string Hello()
{
return "Hello";
}
}
}
class 跟它的 method 記得都要設成 public
再來回到 Console 專案上,右鍵點專案 -> 加入
-> 參考,開啟參考管理員,然後選擇
MyLibrary,最後按確定
using System;
using MyLibrary;
namespace ConsoleApp
{
internal class Program
{
static void Main(string[] args)
{
Console.Write(MyManager.Hello());
Console.ReadKey();
}
}
}
如果 build 時都沒報錯,而且可以在 console
上看到 hello,那 dll 專案就成功了。
為 DLL 專案加入資源:
右鍵點選 DLL 專案 -> 加入 ->
新增資料夾,我把新增的資料夾命名為 Image,然後再放入這張圖
圖片建置動作是"內容",build 完的 dll 是 4KB |
圖片建置動作是"內嵌資源",build 完的 dll 是 212KB |
212 - 4 = 208,確實就是我們這張 jpg
在磁碟上的大小,可見圖片真的有包在 dll 裡。
從 DLL 檔裡把圖片給取出:
繼續處理 DLL 專案,首先需要呼叫 Assembly.GetExecutingAssembly 來取得 DLL 專案的 Assembly。我在觀察 Assembly
類別有什麼方法能呼叫時,有看到它有這方法
嗯...
看起來是我需要的,所以就寫了程式碼來試試這個功能,我為我的 MyManager
類別新增了 GetResourceInfo 方法。要使用 Assembly 要引用
System.Reflection,要使用 List<> 跟 ToList 擴充方法,需要引用
System.Collections.Generic 跟 System.Linq。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
namespace MyLibrary
{
public class MyManager
{
public static string Hello()
{
return "Hello";
}
public static List<string> GetResourceInfo()
{
Assembly assembly = Assembly.GetExecutingAssembly();
return assembly.GetManifestResourceNames().ToList();
}
}
}
然後 Console 專案這樣寫
using System;
using MyLibrary;
namespace ConsoleApp
{
internal class Program
{
static void Main(string[] args)
{
foreach(string sName in MyManager.GetResourceInfo())
{
Console.WriteLine(sName);
}
Console.ReadKey();
}
}
}
Console 專案成功執行後,可以看到以下的結果
所以,在 MyManager 加入 GetResourceStream 的方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.IO;
namespace MyLibrary
{
public class MyManager
{
public static string Hello()
{
return "Hello";
}
public static List<string> GetResourceInfo()
{
Assembly assembly = Assembly.GetExecutingAssembly();
return assembly.GetManifestResourceNames().ToList();
}
public static Stream GetResourceStream(string sName)
{
Assembly assembly = Assembly.GetExecutingAssembly();
return assembly.GetManifestResourceStream(sName);
}
}
}
然後 Console 的專案這樣寫
using System;
using System.Reflection;
using MyLibrary;
using System.IO;
namespace ConsoleApp
{
internal class Program
{
static void Main(string[] args)
{
string sCurrentPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string sImagePath = Path.Combine(sCurrentPath, "saved.jpg");
using(FileStream fileStream = new FileStream(sImagePath, FileMode.Create, FileAccess.Write))
{
Stream stream = MyManager.GetResourceStream("MyLibrary.Image.499106987838013856.jpg");
stream.CopyTo(fileStream);
}
Console.ReadKey();
}
}
}
12行 : 取得程式目前執行路徑。
13行 : 要把圖片存成 "saved.jpg"
17行 : 這邊傳入的 string 名稱就是我們前一個實作看到的那個。
18行 : 用 stream 的 CopyTo 把內容複製到 FileStream 裡。
程式執行結束後,可以在 Console 專案的 bin/Debug 目錄下看到那個 saved.jpg 檔案,確實就是我們放入 DLL 的那張圖片。
沒有留言:
張貼留言