임베디드 리소스의 "경로"를 어떻게 찾을 수 있습니까?


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
내 임베디드 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
@UchihaItachi 질문은 또한 질문하는 사람이 직면 한 문제, 그의 접근 방식 및 지금까지 시도한 방법을 알려줍니다. Rudolph는 질문에 직접 답하지 않지만 문제를 해결하기위한 또 다른 접근 방식을 제시합니다. 대부분의 경우이 방법은 더 편리하고 안전하며 일반적입니다. 이 답변은 도움이됩니다. 사람들의 답변을 차단해야하는 이유를 이해할 수 없습니다. 찬성 / 반대 버튼은 이유가 있습니다.
Nin

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.namespace라는 네임 스페이스의 폴더 구조 resources \ xml에있는 my.xml의 스트림을 반환합니다.


6
또한 폴더의 대시 ( '-')는 밑줄 ( '_')로 대체됩니다. 다른 기호도있을 수 있습니다. 동일한 방법을 사용할 수 있도록 컴파일러가 어떻게 수행하는지보고 싶습니다.
보이 코 Karadzhov
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.