practical-aspnetcore
practical-aspnetcore copied to clipboard
Dependency Injection example 3 - CurrentDomain.GetAssemblies()
Looking at https://github.com/dodyg/practical-aspnetcore/blob/net6.0/projects/dependency-injection/dependency-injection-3/Program.cs - as far as I know this code
var types = System.AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(x => x.GetTypes())
.Where(p => type.IsAssignableFrom(p) && p.IsClass);
will find only types in assemblies loaded to this moment. For perf reason, .NET loads assemblies only when needed, so GetAssemblies()
is often only a subset of all the app dependencies/assemblies.
A couple of options (not sure if there are more or if there's a way to force all assemblies to be discoverable):
- introducing static references to all assemblies, so they are loaded when the app starts
- scanning the folder and manually load each assembly before calculating
types
(caching the result if possible, so this is done only once or on demand)
Hi @dluc
Just landing to this issue, you meant something like referencing the .dll first by reflection and then retrieves a list of assemblies for instance? I would like to contribute to this if possible :)
@dalbarracin yes that should work. Referencing to any class inside each DLL with force .NET to load all assemblies, then GetAssemblies will return the full list. Something like this:
string[] NS_TO_IGNORE = { "System." };
string[] referencedPaths = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll");
foreach (var path in referencedPaths)
{
var filename = path.Split(Path.DirectorySeparatorChar).LastOrDefault();
if (filename != null && !NS_TO_IGNORE.Any(x => filename.StartsWith(x)))
AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(path));
}
var types = System.AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(x => x.GetTypes())
.Where(p => type.IsAssignableFrom(p) && p.IsClass);
Sounds doable @dluc 👍🏻
Also, just to avoid leaking types it would probably be a good idea to create a new AppDomain and Load/Unload the Assemblies if needed but I think that's out of scope.
I will work on this.