Exception while dynamically creating assemblies using DefineDynamicAssembly on non-current AppDomain
Asked Answered
P

1

6

I want to dynamically create assemblies in the integration tests for the purpose of testing some assembly manipulation classes. If I use the following code to create the testing assemblies:

var domain = AppDomain.CurrentDomain;

var builder = domain.DefineDynamicAssembly(
    new AssemblyName(assemblyName),
    AssemblyBuilderAccess.Save,
    directory);

builder.Save(fileName);

then everything runs ok, the assemblies are created in the required location, but as part of this they are also loaded to the current AppDomain, which I don't want.

So I though about creating the assemblies using the separate AppDomain:

var domain = AppDomain.CreateDomain("Test");

...

But running the code throws an exception at the line var builder = domain.DefineDynamicAssembly(...);:

System.Runtime.Serialization.SerializationException: Type 'System.Reflection.Emit.AssemblyBuilder' in assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.

I have no clue how this relates to calling DefineDynamicAssembly on a non-current AppDomain. All I find online is mostly about executing assemblies in separate domains. Perhaps what I'm trying to do here is just too specific, too advanced or even not recommended at all, but it would enable me to test all our assembly manipulation code.

Can someone please point me in the right direction?

Principate answered 20/11, 2012 at 7:8 Comment(5)
Could you post actual code that throws that exception? And why exactly don't you want to load it into the current AppDomain? If you're worried about memory, you might want to try AssemblyBuilderAccess.RunAndCollect instead.Coretta
@Coretta The exception is being thrown at the var builder = domain.DefineDynamicAssembly(...); line, I updated the question.Principate
@Coretta I do not want the "fake" assemblies, that are not shared between the tests to get into the global scope. Though for now it is mostly for purity reasons, some of those assemblies will probably contain some code later on, which could be a problem then.Principate
You'll need to run the code that creates the assembly in the other appdomain as well.Ptisan
@HansPassant I was afraid it would be something like this. I'll see what can be done about it, I'll probably change my approach to this entirely. Thanks for the comment.Principate
M
1

I got it working by executing the code in the other AppDomain, like suggested.

var appdomain = AppDomain.CreateDomain("CreatingAssembliesAndExecutingTests", null,
   new AppDomainSetup { ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase });

appdomain.DoCallBack(() =>
{
   var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("temp"), AssemblyBuilderAccess.Run);
   var module = assembly.DefineDynamicModule("DynModule");
   var typeBuilder = module.DefineType("MyTempClass", TypeAttributes.Public | TypeAttributes.Serializable);
});

Remark you have to specify the ApplicationBase on the AppDomainSetup in order to find the delegate in the other AppDomain.

Minnich answered 20/2, 2013 at 15:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.