Assembly cannot find assembly reference when compiling to memory using CodeDomProvider

I am trying to compile some code into memory at runtime using CodeDomProvider.

The code I'm compiling has a link to an external assembly, which I include in the options used to compile the code.

When I compile into memory and try to use reflection in the assembly generated in the Visual Studio add-in, it throws an exception saying that it cannot find the link to the assembly.

(Exception)
"Cannot load one or more of the requested types. Get more information about the LoaderExceptions object."

(LoaderException)
"{" Failed to load file or assembly "Dynamo.Jiss.Task, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null" or one of its dependencies. The system cannot find the specified file. ":" Dynamo.Jiss.Task, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null "}"

I tried to reference the assembly from different places using the absolute path.

The exact same code works fine if it is run from the Console application, and it also works fine in the add-in if I don't compile to memory.
Removing a link to an external assembly and the code that references it also works when compiling to memory, so it is likely that as the exception is described, there is a problem loading the referenced assembly.

Does anyone have an idea why compilation into memory and assembly reference do not work in add-in?

Are there any limitations in running AppDomain or something I should know about? (now my best guess)

Should it be in a specific folder? using relative path? Security Settings? need to sign? any ideas?


What I'm trying to achieve is a way to put files with a specific extension into a project and let it automatically compile it, and if it implements the ITask interface (from an external assembly), it will call the Setup () method, which allows the code to connect to Visual Studio events and execute tasks / scripts while listening to different events. Thus, I can easily execute text templates if another file has been modified, or Combine and Minify files for different events (document saving, assembly, etc.).

Something like this already exists (to save me from the pain)? :)

+4
source share
1 answer

This most likely happens because you tell CodeDom to build the assembly in memory (this is really a lie, because it temporarily generates a disk, loads it, and then deletes the file). The fact is that the compilation directory for compiling CodeDom is not the same as the one you use to compile it. That is, if you are working in bin \ Debug, the CodeDom assembly is generated up to% temp%.

You can solve this in one of two ways that I can think of:

  • Compile the CodeDom assembly in the same way as your running assembly.

    myCodeProvider.GenerateInMemory = false; // may not be necessary...haven't tried this in a while myCodeProvider.OutputAssembly = string.Format(@"{0}\{1}", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location, "mydll.dll"); 
  • Refer to the AssemblyResolve event and provide the CodeDom assembly to the requested assembly.

     AppDomain.CurrentDomain.AssemblyResolve += OnCurrentDomainAssemblyResolve private static Assembly OnCurrentDomainAssemblyResolve(object sender, ResolveEventArgs args) { // this is absurdly expensive...don't do this more than once, or load the assembly file in a more efficient way // also, if the code you're using to compile the CodeDom assembly doesn't/hasn't used the referenced assembly yet, this won't work // and you should use Assembly.Load(...) foreach (Assembly @assembly in AppDomain.CurrentDomain.GetAssemblies()) { if (@assembly.FullName.Equals(args.Name, StringComparison.OrdinalIgnoreCase)) { return @assembly; } } } 
+7
source

All Articles