-
Notifications
You must be signed in to change notification settings - Fork 144
Reflection & Assemblies
Mehdi Hadeli edited this page Jan 9, 2023
·
26 revisions
- Using Type.GetType with .NET Core / Dynamically Loading .NET Standard Assemblies in .NET Core
- Get All Types in an Assembly ⭐
- Getting Assemblies Is Harder Than You Think In C# ⭐⭐
- C# Reflection: Get all active assemblies in a solution? ⭐
- .NET How-Tos: find all application Assemblies ⭐⭐
- How to prevent ReflectionTypeLoadException when calling Assembly.GetTypes() ⭐
- GetReferencedAssemblies not returning all referenced assemblies ⭐⭐
- Best Practices for Assembly Loading ⭐
- AppDomain.GetAssemblies Method
- Assembly.Load Method
- Assembly.GetExecutingAssembly Method
- Assembly.GetCallingAssembly Method
- Assembly.GetExecutingAssembly()
- Application domains ⭐
- Back to Basics: When does a .NET Assembly Dependency get loaded ⭐⭐⭐
- Difference between AppDomain.GetAssemblies and BuildManager.GetReferencedAssemblies
- How can I get ApplicationPartAttribute within .net5 class library?
- Share controllers, views, Razor Pages and more with Application Parts
- Using AssemblyLoadContext for isolation, respecting transitive dependencies ⭐
- Is there a way to force all referenced assemblies to be loaded in to the app domain? ⭐
- Assembly Loadcontext ⭐
- Understanding How Assemblies Load in C# .NET ⭐⭐
- How the Runtime Locates Assemblies ⭐
- Issue: Problem with loading AppDomiain.CurrentDomain.GetAllAsseblies() in Xunit ⭐⭐
- Note:
AppDomain
contains loaded assemblies, but if AppDomain assemblies have a reference to other assemblies they are lazy, and it loads just needed assemblies. - Notes: Assemblies are lazy loaded, this means they load just assemblies they need (for example in startup). So using
AppDomain.GetAssemblies()
is not reliable (it is possible to getReflectionTypeLoadException
, because some dependent type assembly are lazy and not loaded yet) but sometimes it works, and we are lucky. - Note: in Xunit and with
dotnet test
runner instead of loading just needed assemblies lazily, it loads all referenced assemblies (all dlls in the bin - shadow copy) but in the rider test runner it works fine, with this side effect and usingAppDomiain.CurrentDomain.GetAllAsseblies()
we have more assemblies and that is possible some of their internal dependencies not loaded, and it is possible to getReflectionTypeLoadException
. Because reference assemblies have some lazy references assemblies, this means that if we call it during bootstrap, and we haven’t touched at least one type per Assembly, their referenced assembly will not load until they are used (by calling a method on these reference assemblies).
One example for this is Hypothesist
assemblies which is load with its dependent assemblies doesn't load, and we get ReflectionTypeLoadException
because it can't find correspond dependent Assembly version MassTransit.
It is better to use GetReferencedAssemblies
AppDomain.CurrentDomain.GetAssemblies().ToArray();
Assemblies load by AppDomain
based on their code path
and their code usage. Assembly will add to AppDomain dynamically by Jit when visit one of assembly class method.
We could load all references assembly with using this helper function, and load all references
assemblies explicitly
with Assembly.Load(reference)
:
ReflectionUtilities.GetAllReferencedAssemblies(Assembly.GetCallingAssembly()).ToArray();
public static IEnumerable<Assembly> GetAllReferencedAssemblies(Assembly? rootAssembly)
{
var list = new HashSet<string>();
var stack = new Stack<Assembly?>();
var root = rootAssembly ?? Assembly.GetEntryAssembly();
stack.Push(root);
do
{
var asm = stack.Pop();
if (asm == null)
break;
yield return asm;
foreach (var reference in asm.GetReferencedAssemblies())
{
if (!list.Contains(reference.FullName))
{
// loading assemblies explicitly, because assemblies are loaded lazily
stack.Push(Assembly.Load(reference));
list.Add(reference.FullName);
}
}
}
while (stack.Count > 0);
}