Dynamically loading assemblies for reflection without locking the files.
I was recently asked to write a class which dynamically loaded assemblies, and perform reflection on them, without permanently loading the files into the application domain and without locking the files. Unfortunately, and surprisingly the Assembly.ReflectionOnlyLoadFrom(string filename) method also locks files, which in my opinion defeats the purpose. So I had to fall back on the strategy of loading the assembly into a temporary application domain, reflect on the assembly and unload the application domain thus unlocking the file and unloading it from memory.
By using the LoadTypes method in the TypeFinder class you can query an assembly for a particular attribute.
internal class TypeFinder
{
private
class AssemblyReflector
: MarshalByRefObject
{
private
IEnumerable<string>
EnumerateTypes(string assemblyFilename)
{
Assembly
asm = Assembly.LoadFile(assemblyFilename);
if
(asm == null) throw
new Exception("Assembly not found");
foreach
(Type t in
asm.GetTypes())
{
if
(t.GetCustomAttributes(typeof(SomeAttribute), true).FirstOrDefault() != null)
{
yield return
t.AssemblyQualifiedName;
}
}
}
public
string[] LoadTypes(string
assemblyFilename)
{
return
EnumerateTypes(assemblyFilename).ToArray();
}
}
public string[] LoadTypes(string
assemblyFilename)
{
AppDomain
appDomain = AppDomain.CreateDomain("TypeFinder");
try
{
AssemblyReflector
ar = (AssemblyReflector)appDomain.CreateInstanceAndUnwrap(typeof(AssemblyReflector).Assembly.FullName,
typeof(AssemblyReflector).FullName);
return
ar.LoadTypes(assemblyFilename);
}
finally
{
AppDomain.Unload(appDomain);
}
}
}