ฉันจะค้นพบ“ เส้นทาง” ของทรัพยากรที่ฝังอยู่ได้อย่างไร


110

ฉันกำลังจัดเก็บ PNG เป็นทรัพยากรที่ฝังไว้ในแอสเซมบลี จากภายในแอสเซมบลีเดียวกันฉันมีโค้ดดังนี้:

Bitmap image = new Bitmap(typeof(MyClass), "Resources.file.png");

ไฟล์ชื่อ "file.png" ถูกเก็บไว้ในโฟลเดอร์ "Resources" (ภายใน Visual Studio) และถูกทำเครื่องหมายว่าเป็นทรัพยากรแบบฝัง

รหัสล้มเหลวโดยมีข้อยกเว้นว่า:

ไม่พบทรัพยากร MyNamespace.Resources.file.png ในคลาส MyNamespace.MyClass

ฉันมีรหัสที่เหมือนกัน (ในแอสเซมบลีอื่นกำลังโหลดทรัพยากรอื่น) ซึ่งใช้งานได้ ดังนั้นฉันจึงรู้เทคนิคคือเสียง ปัญหาของฉันคือฉันใช้เวลาส่วนใหญ่ในการพยายามคิดว่าเส้นทางที่ถูกต้องคืออะไร หากฉันสามารถสอบถาม (เช่นในดีบักเกอร์) แอสเซมบลีเพื่อค้นหาเส้นทางที่ถูกต้องนั่นจะช่วยฉันไม่ต้องปวดหัว

คำตอบ:


198

สิ่งนี้จะทำให้คุณได้รับสตริงอาร์เรย์ของทรัพยากรทั้งหมด:

System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();

3
เฮ้ฉันจะรับพา ธ โฟลเดอร์ทรัพยากรเพื่อกำหนดเป็นรูท Dir สำหรับเซิร์ฟเวอร์ http แบบฝังตัวของฉันได้อย่างไร
lazzy_ms

45

ฉันพบว่าตัวเองลืมวิธีทำทุกครั้งเช่นกันดังนั้นฉันจึงห่อสองหนึ่งสมุทรที่ฉันต้องการในชั้นเรียนเล็ก ๆ :

public class Utility
{
    /// <summary>
    /// Takes the full name of a resource and loads it in to a stream.
    /// </summary>
    /// <param name="resourceName">Assuming an embedded resource is a file
    /// called info.png and is located in a folder called Resources, it
    /// will be compiled in to the assembly with this fully qualified
    /// name: Full.Assembly.Name.Resources.info.png. That is the string
    /// that you should pass to this method.</param>
    /// <returns></returns>
    public static Stream GetEmbeddedResourceStream(string resourceName)
    {
        return Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
    }

    /// <summary>
    /// Get the list of all emdedded resources in the assembly.
    /// </summary>
    /// <returns>An array of fully qualified resource names</returns>
    public static string[] GetEmbeddedResourceNames()
    {
        return Assembly.GetExecutingAssembly().GetManifestResourceNames();
    }
}

19

ฉันเดาว่าชั้นเรียนของคุณอยู่ในเนมสเปซอื่น วิธีที่ยอมรับได้ในการแก้ปัญหานี้คือการใช้คลาสทรัพยากรและทรัพยากรที่พิมพ์ผิด:

ProjectNamespace.Properties.Resources.file

ใช้ตัวจัดการทรัพยากรของ IDE เพื่อเพิ่มทรัพยากร


คุณพูดถูกชั้นเรียนของฉันอยู่ในเนมสเปซอื่น ดูเหมือนว่าโฟลเดอร์ Resources จะอยู่ภายใต้เนมสเปซที่ระบุเป็นเนมสเปซเริ่มต้นในการกำหนดค่าโปรเจ็กต์ซึ่งด้วยเหตุผลหลายประการไม่ใช่เนมสเปซที่คลาสนี้เป็นส่วนหนึ่งของ ฉันสงสัยว่าคุณถูกต้องเช่นกันเกี่ยวกับการใช้แนวทางที่แตกต่างออกไปโดยสิ้นเชิง แต่เนื่องจากฉันต้องสอดคล้องกับรหัสเดิมจึงอยู่นอกเหนือการควบคุมของฉัน
Rob

7
สิ่งนี้จะคว้าทรัพยากรไม่ใช่เส้นทางของไฟล์
Uchiha Itachi

3
@UchihaItachi นั่นเป็นเหตุผลที่ฉันเสนอคำตอบนี้อย่างชัดเจนว่าเป็นวิธีอื่น (และเป็นที่ยอมรับ) ในการแก้ปัญหาพื้นฐานแทนที่จะตอบคำถามคำต่อคำ (ซึ่งมีคำตอบอยู่แล้วในทุกอัตรา)
Konrad Rudolph

1
@ อุจิวะอิทาจิคำถามยังบอกถึงปัญหาที่ผู้ถามกำลังเผชิญแนวทางของเขาคืออะไรและเขาพยายามอย่างไรจนถึงตอนนี้ แม้ว่ารูดอล์ฟจะไม่ได้ตอบคำถามโดยตรง แต่เขาก็พูดถึงแนวทางอื่นในการแก้ปัญหา ในกรณีส่วนใหญ่วิธีนี้สะดวกปลอดภัยและเป็นเรื่องธรรมดามากกว่า คำตอบนี้มีประโยชน์ ฉันไม่เข้าใจว่าทำไมคุณต้องพยายามปิดคำตอบของผู้อื่น ปุ่มโหวตขึ้น / โหวตลงมีเหตุผล
นิน

5

ฉันใช้วิธีการต่อไปนี้เพื่อดึงทรัพยากรแบบฝัง:

    protected static Stream GetResourceStream(string resourcePath)
    {
        Assembly assembly = Assembly.GetExecutingAssembly();
        List<string> resourceNames = new List<string>(assembly.GetManifestResourceNames());

        resourcePath = resourcePath.Replace(@"/", ".");
        resourcePath = resourceNames.FirstOrDefault(r => r.Contains(resourcePath));

        if (resourcePath == null)
            throw new FileNotFoundException("Resource not found");

        return assembly.GetManifestResourceStream(resourcePath);
    }

จากนั้นฉันเรียกสิ่งนี้ด้วยเส้นทางในโครงการ:

GetResourceStream(@"DirectoryPathInLibrary/Filename")

3

ชื่อของทรัพยากรคือช่องว่างชื่อบวกกับช่องชื่อ "หลอก" ของเส้นทางไปยังไฟล์ ช่องว่างชื่อ "หลอก" สร้างขึ้นโดยโครงสร้างโฟลเดอร์ย่อยโดยใช้ \ (แบ็กสแลช) แทน (จุด)

public static Stream GetResourceFileStream(String nameSpace, String filePath)
{
    String pseduoName = filePath.Replace('\\', '.');
    Assembly assembly = Assembly.GetExecutingAssembly();
    return assembly.GetManifestResourceStream(nameSpace + "." + pseduoName);
}

สายต่อไปนี้:

GetResourceFileStream("my.namespace", "resources\\xml\\my.xml")

จะส่งคืนสตรีมของ my.xml ที่อยู่ในทรัพยากรโครงสร้างโฟลเดอร์ \ xml ในช่องว่างชื่อ: my.namespace


6
นอกจากนี้ขีดกลาง ('-') ในโฟลเดอร์จะถูกแทนที่ด้วยเครื่องหมายขีดล่าง ('_') อาจมีสัญลักษณ์อื่นด้วย ฉันต้องการดูว่าคอมไพเลอร์ทำงานอย่างไรเพื่อให้เราสามารถใช้วิธีการเดียวกันได้
Boyko Karadzhov
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.