Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieving embedded resources with special characters

I'm having a problem getting streams for embedded resources. Most online samples show paths that can be directly translated by changing the slash of a path to a dot for the source (MyFolder/MyFile.ext becomes MyNamespace.MyFolder.MyFile.ext). However when a folder has a dot in the name and when special characters are used, manually getting the resource name does not work. I'm trying to find a function that can convert a path to a resource name as Visual Studio renames them when compiling..

These names from the solution ...

  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.2/jQuery.UI.js

... are changed into these names in the resources ...

  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

Slashes are translated to dots. However, when a dot is used in a folder name, the first dot is apparently considered an extension and the rest of the dots are changed to be prefixed with an underscore. This logic does not apply on the jQuery.js file, though, maybe because the 'extension' is a single number? Here's a function able to translate the issues I've had so far, but doesn't work on the jQuery.js path.

    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 );
    }

Is there a function that can change the names for me? What is it? Or where can I find all the rules so I can write my own function? Thanks for any assistance you may be able to provide.

like image 770
Deathspike Avatar asked Apr 24 '11 09:04

Deathspike


People also ask

How do you read embedded files?

Method 1: Add existing file, set property to Embedded Resource. Add the file to your project, then set the type to Embedded Resource . NOTE: If you add the file using this method, you can use GetManifestResourceStream to access it (see answer from @dtb).

What is an embedded resource?

Embedded resource has no predefined structure: it is just a named blob of bytes. So called “. resx” file is a special kind of embedded resource. It is a string -to-object dictionary that maps a name to an object. The object may be a string , an image, an icon, or a blob of bytes.

How do I add embedded resources to Visual Studio?

Open Solution Explorer add files you want to embed. Right click on the files then click on Properties . In Properties window and change Build Action to Embedded Resource . After that you should write the embedded resources to file in order to be able to run it.


3 Answers

This is kinda a very late answer... But since this was the first hit on google, I'll post what I've found!

You can simply force compiler to name the embedded resource as you want it; Which will kinda solves this problem from the beginning... You've just got to edit your csproj file, which you normally do if you want wildcards in it! here is what I did:

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

In this case, I'm telling Visual studio, that I want all the files in "some folder" to be imported as embedded resources. Also I want them to be shown under "some folder", in VS solution explorer (this is link tag). And finally, when compiling them, I want them to be named exactly with same name and address they had on my disk, with only "somefolder:\" prefix. The last part is doing the magic.

like image 194
Ali1S232 Avatar answered Oct 06 '22 20:10

Ali1S232


This is what I came up with to solve the issue. I'm still open for better methods, as this is a bit of a hack (but seems to be accurate with the current specifications). The function expects a segment from an Uri to process (LocalPath when dealing with web requests). Example call is below..

    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 );
    }

Example call..

    var testResourceName = _GetResourceName( new String[] {
        "/",
        "Scripts/",
        "jQuery.UI-1.8.12/",
        "jQuery-_.UI.js"
    });
like image 20
Deathspike Avatar answered Oct 06 '22 20:10

Deathspike


Roel,

Hmmm... This is a hack, but I guess it should work. Just define an empty "Marker" class in each directory which contains resources, then get the FullName of it's type, remove the class name from end and wala: there's your decoded-path.

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

I'm sure there's a "better" way to do it... with a LOT more lines of code; and this one has the advantage that Microsoft maintains it when they change stuff ;-)

Cheers. Keith.

like image 20
corlettk Avatar answered Oct 06 '22 20:10

corlettk