Using System.Reflection and resources in Phalanger

162 views Asked by At

I need to embed some resource in a pure compiled dll written in php using phalanger. These are txt files tha I set in visual studio as "Embedded Resource".

My problem is that I cannot use the Assembly class to get the resource using GetManifestResourceStream.

I tried code like this: use System\Reflection\Assembly

$asm = Assembly::GetExecutingAssembly(); //this gives me mscorlib instead of my dll
$str = $asm->GetManifestResourceStream("name");

My question is: how do I get access to embedded resources in phalanger? Many thanks

2

There are 2 answers

1
Jakub Míšek On BEST ANSWER

I'm not sure, why Assembly::GetExecutingAssembly() returns an incorrect value. Anyway to workaround the $asm value, use following code:

$MyType = CLRTypeOf MyProgram;
$asm = $MyType->Assembly;

Then you can access embedded resources as you posted

$asm->GetManifestResourceStream("TextFile1.txt");

or you can include standard resource file (.resx) into your project, and use \System\Resources\ResourceManager

$this->manager = new \System\Resources\ResourceManager("",$asm);
$this->manager->GetObject("String1",null);

Just note, currently there can be just one .resx within Phalanger project

0
weirdan On

This question is old, but the part of the Phalanger code (Php.Core.Emit.AddResourceFile() method) responsible for this hasn't changed since this was asked. I faced the same problem and solved it in (almost) non-hacky way. You have to provide alternative name (/res:/path/to/filename,alternative-name) for this to work though.

$asm = clr_typeof('self')->Assembly;
$resourceStream = $asm->GetManifestResourceStream("filename");
$reader = new \System\Resources\ResourceReader($resourceStream);

$type = $data = null;
$reader->GetResourceData("alternative-name", $type, $data);

// and still there are 4 excess bytes
// representing the length of the resource
$data = \substr($data, 4);
$stream  = new IO\MemoryStream($data);

// after this $stream is usable as you would expect

Straightforward GetManifestResourceStream() (as suggested by Jakub) does not work because Phalanger does not use System.Reflection.Emit.ModuleBuilder.DefineManifestResource() (like I think it should when supplied with unrecognized file format). It uses ModuleBuilder.DefineResource() which returns ResourceWriter instead, that only really suited for .resources files. And this is what dictates the requirement to use ResourceReader when you need to read your resource.

Note: This answer applies to Phalanger master branch at the time of writing and prior versions since circa 2011. Noted because it looks like a bug (especially the need to use both original and alternative names).