Referencing in-memory assembly on compile

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Andrus

    Referencing in-memory assembly on compile

    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.CShar p.CSharpCodePro vider provider = new
    Microsoft.CShar p.CSharpCodePro vider();

    CompilerParamet ers compilerParamet ers = new CompilerParamet ers {
    GenerateInMemor y = true
    };

    CompilerResults compilerResults =
    provider.Compil eAssemblyFromSo urce(compilerPa rameters, "public
    class Test {}");
    if (compilerResult s.Errors.HasErr ors)
    throw new ApplicationExce ption("Unexpect ed compile error");

    var asm1 = compilerResults .CompiledAssemb ly;

    compilerParamet ers.ReferencedA ssemblies.Add(a sm1.FullName);

    compilerResults =
    provider.Compil eAssemblyFromSo urce(compilerPa rameters, "public
    class Test1 : Test {}");

    if (compilerResult s.Errors.HasErr ors) {
    string msg;
    msg = compilerResults .Errors.Count.T oString() + " 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);
    }
    }
    }



  • Fernando Rodriguez, MCP

    #2
    Re: Referencing in-memory assembly on compile

    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" <kobruleht2@hot .eewrote in message
    news:%230OC8DHr IHA.3940@TK2MSF TNGP03.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.CShar p.CSharpCodePro vider provider = new
    Microsoft.CShar p.CSharpCodePro vider();
    >
    CompilerParamet ers compilerParamet ers = new CompilerParamet ers {
    GenerateInMemor y = true
    };
    >
    CompilerResults compilerResults =
    provider.Compil eAssemblyFromSo urce(compilerPa rameters, "public
    class Test {}");
    if (compilerResult s.Errors.HasErr ors)
    throw new ApplicationExce ption("Unexpect ed compile error");
    >
    var asm1 = compilerResults .CompiledAssemb ly;
    >
    compilerParamet ers.ReferencedA ssemblies.Add(a sm1.FullName);
    >
    compilerResults =
    provider.Compil eAssemblyFromSo urce(compilerPa rameters, "public
    class Test1 : Test {}");
    >
    if (compilerResult s.Errors.HasErr ors) {
    string msg;
    msg = compilerResults .Errors.Count.T oString() + " 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);
    }
    }
    }
    >
    >
    >

    Comment

    • Andrus

      #3
      Re: Referencing in-memory assembly on compile

      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.


      Comment

      Working...