By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,705 Members | 2,013 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,705 IT Pros & Developers. It's quick & easy.

Referencing in-memory assembly on compile

P: n/a
I need compile in-memory assembly which references to other in-memory
assembly.

Compiling second assembly fails with error

Line: 0 - Metadata file 'eed7li9m, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null' could not be found

Saving assembly to Windows temp directory for referencing only creates huge
amout of temporary
files. I don't know any way to delete those files since they are locked by
loaded assemblies.
Creating separate Appdomain causes issues when I want to pass my
application types.

How to fix ?

Is is possible/reasonabe to compile assembly twice: one compile to memory
and second compile to temporary directory for reference only ?
Or is it possible to delete those temporary files ?

Andrus.
using System;
using System.CodeDom.Compiler;
using System.Windows.Forms;

class Program {
static void Main() {
Microsoft.CSharp.CSharpCodeProvider provider = new
Microsoft.CSharp.CSharpCodeProvider();

CompilerParameters compilerParameters = new CompilerParameters {
GenerateInMemory = true
};

CompilerResults compilerResults =
provider.CompileAssemblyFromSource(compilerParamet ers, "public
class Test {}");
if (compilerResults.Errors.HasErrors)
throw new ApplicationException("Unexpected compile error");

var asm1 = compilerResults.CompiledAssembly;

compilerParameters.ReferencedAssemblies.Add(asm1.F ullName);

compilerResults =
provider.CompileAssemblyFromSource(compilerParamet ers, "public
class Test1 : Test {}");

if (compilerResults.Errors.HasErrors) {
string msg;
msg = compilerResults.Errors.Count.ToString() + " Errors:";
for (int x = 0; x < compilerResults.Errors.Count; x++)
msg = msg + "\r\nLine: " +
compilerResults.Errors[x].Line.ToString() + " - " +
compilerResults.Errors[x].ErrorText;

//Causes Line: 0 - Metadata file 'eed7li9m, Version=0.0.0.0,
Culture=neutral,
//PublicKeyToken=null' could not be found
MessageBox.Show(msg);
}
}
}

Jun 27 '08 #1
Share this Question
Share on Google+
2 Replies


P: n/a
You need to use reflection to read the public API of the assembly that you
want to reference, then generate code for skeleton for all the public
classes and it's members, also add an static initializer that takes in an
Assembly object reference and saves it to a static field. Then add two
fields, one of type System.Object called _instance, and one of type
System.Type called _instanceType to all your generated classes and on the
constructors use the static Assembly object's CreateInstance to create an
instance of the type on the referenced assembly and save it to the
_instanceField. Then use the GetTypes() method to get an array of the types
that the referenced assembly contains, iterate through it comparing the
..FullName property with the full name of the type you're referencing and
when you find it save it to the _instanceType field. Now on you generated
methods you can use the Invoke method of the _instanceType field to call
methods on your remote class. Then you need to add this generated code to
the code that you're trying to compile. Additionally you need to add one
more static initializer method to the code being compiled, it should take in
the Assembly object reference and pass it to the static initializer of the
generated code. Finally after you compile the assembly and load it you must
call the static initializer pass the "reference to the referenced assembly"
to it.

It's not as hard as it sounds since reflection will give you all the info
that you need to generate the code tree.

Hope that helps,
Fernando L Rodriguez, MCP

"Andrus" <ko********@hot.eewrote in message
news:%2****************@TK2MSFTNGP03.phx.gbl...
>I need compile in-memory assembly which references to other in-memory
assembly.

Compiling second assembly fails with error

Line: 0 - Metadata file 'eed7li9m, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null' could not be found

Saving assembly to Windows temp directory for referencing only creates
huge
amout of temporary
files. I don't know any way to delete those files since they are locked by
loaded assemblies.
Creating separate Appdomain causes issues when I want to pass my
application types.

How to fix ?

Is is possible/reasonabe to compile assembly twice: one compile to memory
and second compile to temporary directory for reference only ?
Or is it possible to delete those temporary files ?

Andrus.
using System;
using System.CodeDom.Compiler;
using System.Windows.Forms;

class Program {
static void Main() {
Microsoft.CSharp.CSharpCodeProvider provider = new
Microsoft.CSharp.CSharpCodeProvider();

CompilerParameters compilerParameters = new CompilerParameters {
GenerateInMemory = true
};

CompilerResults compilerResults =
provider.CompileAssemblyFromSource(compilerParamet ers, "public
class Test {}");
if (compilerResults.Errors.HasErrors)
throw new ApplicationException("Unexpected compile error");

var asm1 = compilerResults.CompiledAssembly;

compilerParameters.ReferencedAssemblies.Add(asm1.F ullName);

compilerResults =
provider.CompileAssemblyFromSource(compilerParamet ers, "public
class Test1 : Test {}");

if (compilerResults.Errors.HasErrors) {
string msg;
msg = compilerResults.Errors.Count.ToString() + " Errors:";
for (int x = 0; x < compilerResults.Errors.Count; x++)
msg = msg + "\r\nLine: " +
compilerResults.Errors[x].Line.ToString() + " - " +
compilerResults.Errors[x].ErrorText;

//Causes Line: 0 - Metadata file 'eed7li9m, Version=0.0.0.0,
Culture=neutral,
//PublicKeyToken=null' could not be found
MessageBox.Show(msg);
}
}
}

Jun 27 '08 #2

P: n/a
Fernando,
You need to use reflection to read the public API of the assembly that you
want to reference, then generate code for skeleton for all the public
classes and it's members, also add an static initializer that takes in an
Assembly object reference and saves it to a static field. Then add two
fields, one of type System.Object called _instance, and one of type
System.Type called _instanceType to all your generated classes and on the
constructors use the static Assembly object's CreateInstance to create an
instance of the type on the referenced assembly and save it to the
_instanceField. Then use the GetTypes() method to get an array of the
types that the referenced assembly contains, iterate through it comparing
the .FullName property with the full name of the type you're referencing
and when you find it save it to the _instanceType field. Now on you
generated methods you can use the Invoke method of the _instanceType field
to call methods on your remote class. Then you need to add this generated
code to the code that you're trying to compile. Additionally you need to
add one more static initializer method to the code being compiled, it
should take in the Assembly object reference and pass it to the static
initializer of the generated code. Finally after you compile the assembly
and load it you must call the static initializer pass the "reference to
the referenced assembly" to it.

It's not as hard as it sounds since reflection will give you all the info
that you need to generate the code tree.
Thank you. This looks complicated for me.
Where to find generic code which implements this ?
Currently I implemented code which creates assemblies in windows temp
directory.
In next incovation my application clean temp directory from the assemblies
which are created during previous run.
Is this OK ?
Unfortunately MS Reportviewer control in local mode cannot still find any
dynamic assembly.

Andrus.
Jun 27 '08 #3

This discussion thread is closed

Replies have been disabled for this discussion.