The problem with dynamically loading assemblies in .NET.

We created a small component that takes an identifier, looks at the database record for the assembly / namespace / class, and dynamically loads the instance of the class that we need. It still works, but when you run this code in VS 2010, it does not work.

Private Function AssemblyLoaded(ByVal assemblyFile As String) As Assembly Dim assemblies() As Assembly = AppDomain.CurrentDomain.GetAssemblies For Each asmb As Assembly In assemblies If (asmb.Location = assemblyFile)) Then Return asmb Next Return Nothing End Function 

The first problem is that when an iterator hits the dynamic assembly, there is no asmb.Location and a NotSupportedException. Is there a way to check the unsupported location field without getting an exception?

The second problem: asmb.Location returns the whole path, not just the file name, which means that this function is interrupted every time. If this function determines that the class has not yet been loaded, we try to load it and get an AccessViolationException because the class is already loaded and we cannot "reload" it.

Function change for this:

 Private Function AssemblyLoaded(ByVal assemblyFile As String) As Assembly Dim assemblies() As Assembly = AppDomain.CurrentDomain.GetAssemblies For Each asmb As Assembly In assemblies Try If (asmb.Location.EndsWith(assemblyFile)) Then Return asmb Catch ex As NotSupportedException Continue For End Try Next Return Nothing End Function 

But he feels dirty. Is there a better way to check if the assembly is already loaded and pass it back to the caller? Are the problems above specific for .NET 4.0 or Visual Studio 2010? I have not tried this outside of the IDE, as this requires a fairly significant configuration.

+6
reflection c # visual-studio
source share
3 answers

You can check if the assembly is dynamic by skipping instances of AssemblyBuilder. You must use Path.GetFileName () to isolate the name. Remember that this is not a good idea, since assemblies from different paths may have the same name. But you seem to be stuck with this. Thus:

 Private Function AssemblyLoaded(ByVal assemblyFile As String) As Assembly For Each asmb As Assembly In AppDomain.CurrentDomain.GetAssemblies If TypeOf asmb Is System.Reflection.Emit.AssemblyBuilder Then Continue For If System.IO.Path.GetFileName(asmb.Location) = assemblyFile Then Return asmb Next Return Nothing End Function 

Case sensitivity is something you should deal with, perhaps.

+5
source share

To add to the Hans Passant anwer: for my application (C # 4.0), the missing instances of AssemblyBuilder still failed. Turns out there is another System.Reflection.Emit.InternalAssemblyBuilder class that also throws a NotSupportedException when accessing Location .

InternalAssemblyBuilder and RuntimeAssembly (the desired type) are internal, so the best I could come up with is (in C #):

 var assemblies = AppDomain.CurrentDomain .GetAssemblies() .Where(assembly => assembly.GetType().Name == "RuntimeAssembly") .Select(assembly => assembly.Location) .ToArray(); 
+2
source share

If you are using .Net 4.0, you should check out Assembly.IsDynamic , which covers all the bases ...

0
source share

All Articles