Vagif Abilov's blog on .NET


.NET 4.0 and NotSupportedException complaining about dynamic assemblies

If you search for “The invoked member is not supported in a dynamic assembly” error message, you will get plenty of results. Some of them related to code that worked in .NET 2.0 and 3.x but suddenly stopped working in .NET 4.0. What may be surprising is that this error comes from the places that have nothing to do with dynamic assemblies. In fact, they are not created in application code.

Here’s an example of the code that can break:

private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    var assemblies = from Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()
                              where !(assembly is System.Reflection.Emit.AssemblyBuilder) &&
                              !assembly.GlobalAssemblyCache &&
                              assembly.CodeBase != Assembly.GetExecutingAssembly().CodeBase
                              select assembly;

    foreach (var assembly in assemblies)
    {
        // rest of the code is skipped
    }
}

What's wrong with this code when it comes to dynamic assemblies? Nothing as long as it's running in CLR prior to .NET 4.0. Apparently the check assembly is System.Reflection.Emit.AssemblyBuilder is no longer enough if you want to detect dynamic assembly under CLR 4.0. There may be dynamic assemblies that pass this test and System.NotSupportedException will be thrown on attempt to call CodeBase property on them, since they CodeBase doesn’t make sense for a dynamic assembly.

However, one additional check helps: a check for assembly full name mathcing System.Reflection.Emit.InternalAssemblyBuilder. So the code above should be rewritten in the following way:

private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    var assemblies = from Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()
                              where !(assembly is System.Reflection.Emit.AssemblyBuilder) &&
                              assembly.GetType().FullName != "System.Reflection.Emit.InternalAssemblyBuilder" &&
                              !assembly.GlobalAssemblyCache &&
                              assembly.CodeBase != Assembly.GetExecutingAssembly().CodeBase
                              select assembly;

    foreach (var assembly in assemblies)
    {
        // rest of the code is skipped
    }
}

Comments

Jack said:

Thanks, for your post. It was very useful in tracking down the problem in a .net 4 migration.

btw .net 4 introduced the Assembly.IsDynamic property ;).

# September 28, 2010 4:42 PM

Andy said:

Thanks a lot for your findings!

It's an elegant way to get rid of errors in .net2 build assembly running under .net4

# March 31, 2011 4:28 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Please add 2 and 5 and type the answer here: