c# - net - ¿Cómo puedo descubrir la "ruta" de un recurso incrustado?
resources c# resx (5)
El nombre del recurso es el espacio de nombre más el espacio de nombre "pseudo" de la ruta al archivo. El espacio de nombre "pseudo" se crea mediante la estructura de la subcarpeta utilizando / (barras diagonales inversas) en lugar de. (puntos)
public static Stream GetResourceFileStream(String nameSpace, String filePath)
{
String pseduoName = filePath.Replace(''//', ''.'');
Assembly assembly = Assembly.GetExecutingAssembly();
return assembly.GetManifestResourceStream(nameSpace + "." + pseduoName);
}
La siguiente llamada:
GetResourceFileStream("my.namespace", "resources//xml//my.xml")
devolverá la secuencia de my.xml que se encuentra en la carpeta-structure resources / xml en el espacio de nombres: my.namespace.
Estoy almacenando un archivo PNG como un recurso incrustado en un ensamblado. Desde dentro del mismo ensamble tengo un código como este:
Bitmap image = new Bitmap(typeof(MyClass), "Resources.file.png");
El archivo, llamado "file.png" se almacena en la carpeta "Recursos" (dentro de Visual Studio) y se marca como un recurso incrustado.
El código falla con una excepción que dice:
Resource MyNamespace.Resources.file.png no se puede encontrar en la clase MyNamespace.MyClass
Tengo un código idéntico (en un ensamblaje diferente, cargando un recurso diferente) que funciona. Entonces sé que la técnica es sólida. Mi problema es que paso mucho tiempo tratando de descubrir cuál es el camino correcto. Si pudiera simplemente consultar (por ejemplo, en el depurador) el ensamblado para encontrar la ruta correcta, eso me ahorraría un montón de dolores de cabeza.
Esto le proporcionará una matriz de cadenas de todos los recursos:
System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
Me encuentro olvidándome de cómo hacer esto cada vez, así que simplemente envuelvo las dos frases sencillas que necesito en una pequeña clase:
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();
}
}
Supongo que tu clase está en un espacio de nombres diferente. La forma canónica de resolver esto sería usar la clase resources y un recurso fuertemente tipado:
ProjectNamespace.Properties.Resources.file
Use el administrador de recursos del IDE para agregar recursos.
Uso el siguiente método para captar recursos incrustados:
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);
}
Luego llamo esto con la ruta en el proyecto:
GetResourceStream(@"DirectoryPathInLibrary/Filename")