2011-04-24 29 views
7

Tengo problemas para obtener transmisiones de recursos incrustados. La mayoría de los ejemplos en línea muestran las rutas que se pueden traducir directamente al cambiar la barra de una ruta a un punto para la fuente (MyFolder/MyFile.ext se convierte en MyNamespace.MyFolder.MyFile.ext). Sin embargo, cuando una carpeta tiene un punto en el nombre y cuando se usan caracteres especiales, no se puede obtener manualmente el nombre del recurso. Estoy tratando de encontrar una función que puede convertir una ruta a un nombre de recurso como Visual Studio les cambia el nombre al compilar ..Recuperar recursos incrustados con caracteres especiales

Estos nombres de la solución ...

  1. contenido/jQuery.UI- 1.8.2/jQuery.UI.css
  2. scripts/jQuery-1.5.2/jquery.js
  3. Scripts/jQuery.jPlayer-2.0.0/jQuery.jPlayer.js
  4. Scripts/jQuery.UI- 1.8.2/jQuery.UI.js

... se cambian en estos nombres de los recursos ...

  1. Content.jQuery.UI_1._8._2.jQuery.UI.css
  2. Scripts.jQuery_1._5._2.jQuery. js
  3. Scripts.jQuery.jPlayer_2._0._0.jQuery.jPlayer.js
  4. Scripts.jQuery.UI_1._8._12.jQuery.UI.js

rayas verticales se convierten en puntos. Sin embargo, cuando se usa un punto en el nombre de una carpeta, el primer punto aparentemente se considera una extensión y el resto de los puntos se cambian para que se les agregue un guión bajo. Sin embargo, esta lógica no se aplica en el archivo jQuery.js, ¿quizás porque la 'extensión' es un número único? Aquí hay una función capaz de traducir los problemas que he tenido hasta ahora, pero no funciona en la ruta jQuery.js.

protected String _GetResourceName(String[] zSegments) 
    { 
     String zResource = String.Empty; 

     for (int i = 0; i < zSegments.Length; i++) 
     { 
      if (i != (zSegments.Length - 1)) 
      { 
       int iPos = zSegments[i].IndexOf('.'); 

       if (iPos != -1) 
       { 
        zSegments[i] = zSegments[i].Substring(0, iPos + 1) 
           + zSegments[i].Substring(iPos + 1).Replace(".", "._"); 
       } 
      } 

      zResource += zSegments[i].Replace('/', '.').Replace('-', '_'); 
     } 

     return String.Concat(_zAssemblyName, zResource); 
    } 

¿Existe alguna función que pueda cambiarme los nombres? ¿Qué es? ¿O dónde puedo encontrar todas las reglas para poder escribir mi propia función? Gracias por cualquier ayuda que pueda brindar.

Respuesta

2

Esto es lo que se me ocurrió para resolver el problema. Todavía estoy abierto para mejores métodos, ya que esto es un poco complicado (pero parece ser exacto con las especificaciones actuales). La función espera que un segmento de un Uri procese (LocalPath cuando se trata de solicitudes web). Ejemplo de llamada es a continuación ..

protected String _GetResourceName(String[] zSegments) 
    { 
     // Initialize the resource string to return. 
     String zResource = String.Empty; 

     // Initialize the variables for the dot- and find position. 
     int iDotPos, iFindPos; 

     // Loop through the segments of the provided Uri. 
     for (int i = 0; i < zSegments.Length; i++) 
     { 
      // Find the first occurrence of the dot character. 
      iDotPos = zSegments[i].IndexOf('.'); 

      // Check if this segment is a folder segment. 
      if (i < zSegments.Length - 1) 
      { 
       // A dash in a folder segment will cause each following dot occurrence to be appended with an underscore. 
       if ((iFindPos = zSegments[i].IndexOf('-')) != -1 && iDotPos != -1) 
       { 
        zSegments[i] = zSegments[i].Substring(0, iFindPos + 1) + zSegments[i].Substring(iFindPos + 1).Replace(".", "._"); 
       } 

       // A dash is replaced with an underscore when no underscores are in the name or a dot occurrence is before it. 
       //if ((iFindPos = zSegments[i].IndexOf('_')) == -1 || (iDotPos >= 0 && iDotPos < iFindPos)) 
       { 
        zSegments[i] = zSegments[i].Replace('-', '_'); 
       } 
      } 

      // Each slash is replaced by a dot. 
      zResource += zSegments[i].Replace('/', '.'); 
     } 

     // Return the assembly name with the resource name. 
     return String.Concat(_zAssemblyName, zResource); 
    } 

Ejemplo de llamada ..

var testResourceName = _GetResourceName(new String[] { 
     "/", 
     "Scripts/", 
     "jQuery.UI-1.8.12/", 
     "jQuery-_.UI.js" 
    }); 
1

Roel,

Hmmm ... Este es un truco, pero supongo que debería funcionar. Simplemente defina una clase "Marker" vacía en cada directorio que contenga recursos, luego obtenga el FullName de su tipo, elimine el nombre de clase de end y wala: allí está su ruta decodificada.

string path = (new MarkerClass()).GetType().FullName.Replace(".MarkerClass", "");

Estoy seguro de que hay un "mejor" forma de hacerlo ... con mucho más líneas de código; y este tiene la ventaja de que Microsoft lo mantiene cuando cambian cosas ;-)

Saludos. Keith.

+0

Gracias por la rápida respuesta de Keith. No puedo encontrar la clase mencionada, aunque parece estar en "Microsoft.Dss.Services.AssemblyEmbeddedResourceService" (No lo tengo localmente). Eso generalmente también significa que mono no tiene una implementación para él, y eso es algo que no puedo ignorar. Quizás hay otras formas? –

+0

Reitero: DEFINE una clase "Marker" vacía en cada directorio que contiene recursos. Acabo de crear el nombre "MarkerClass". Tenía un poco de Google, con la premisa de que HABÍA una manera mejor, y se me ocurrió esta pequeña joya: http://stackoverflow.com/questions/27757/how-can-i-discover-the- path-of-a-embedded-resource ... Espero que sea útil. – corlettk

+0

No se puede definir una clase en un espacio de nombres con puntos (que es exactamente la información que necesito, ¿cómo se codifican los nombres de recursos incrustados?). Una vez que el nombre es correcto, simplemente puedo usar GetManifestResourceStream según su referencia vinculada. –

2

Esto es un poco una respuesta muy tarde ... Pero ya que este fue el primer éxito en Google, ¡publicaré lo que he encontrado!

Simplemente puede forzar al compilador a nombrar el recurso incrustado como lo desee; Lo cual solucionará un poco este problema desde el principio ... ¡Solo tienes que editar tu archivo csproj, que normalmente haces si quieres comodines! esto es lo que hice:

<EmbeddedResource Include="$(SolutionDir)\somefolder\**"> 
    <Link>somefolder\%(RecursiveDir)%(Filename)%(Extension)</Link> 
    <LogicalName>somefolder:\%(RecursiveDir)%(Filename)%(Extension)</LogicalName> 
</EmbeddedResource> 

En este caso, yo estoy diciendo Visual Studio, que quiero que todos los archivos en "alguna carpeta" que se importan como recursos incrustados. También quiero que se muestren en "alguna carpeta", en el explorador de soluciones VS (esta es la etiqueta de enlace). Y finalmente, al compilarlos, quiero que sean nombrados exactamente con el mismo nombre y dirección que tenían en mi disco, con solo el prefijo "somefolder: \". La última parte es hacer la magia.

0

Una respuesta tardía aquí también, busqué en Google antes de intentar esto por mi cuenta y finalmente tuve que hacerlo.

Aquí está la solución que se me ocurrió:

public string ProcessFolderDash(string path) 
    { 
     int dotCount = path.Split('/').Length - 1; // Gets the count of slashes 
     int dotCountLoop = 1; // Placeholder 

     string[] absolutepath = path.Split('/'); 
     for (int i = 0; i < absolutepath.Length; i++) 
     { 
      if (dotCountLoop <= dotCount) // check to see if its a file 
      { 
       absolutepath[i] = absolutepath[i].Replace("-", "_"); 
      } 

      dotCountLoop++; 
     } 

     return String.Join("/", absolutepath); 
    }