Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dependency Injection example 3 - CurrentDomain.GetAssemblies() #333

Open
dluc opened this issue May 23, 2022 · 3 comments
Open

Dependency Injection example 3 - CurrentDomain.GetAssemblies() #333

dluc opened this issue May 23, 2022 · 3 comments

Comments

@dluc
Copy link

dluc commented May 23, 2022

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):

  1. introducing static references to all assemblies, so they are loaded when the app starts
  2. 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)
@dalbarracin
Copy link

dalbarracin commented Oct 2, 2022

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 :)

@dluc
Copy link
Author

dluc commented Oct 3, 2022

@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);

@dalbarracin
Copy link

dalbarracin commented Oct 3, 2022

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants