How to get types from assembly in C#
By FoxLearn 2/4/2025 4:46:16 AM 119
Reflection-only loading methods differ between the .NET Framework and .NET Core. Below are examples of how to perform reflection-only loading in both environments.
.NET Framework - Use Assembly.ReflectionOnlyLoadFrom()
In a .NET Framework project, you can use the Assembly.ReflectionOnlyLoadFrom()
method to load an assembly in reflection-only mode.
var assemblyPath = @"C:\Projects\SampleLibrary\bin\Debug\SampleLibrary.dll"; var assembly = Assembly.ReflectionOnlyLoadFrom(assemblyPath); foreach (var type in assembly.GetTypes()) { Console.WriteLine(type.Name); }
This code will output the following class name:
SampleClass
.NET Core - Use MetadataReader or MetadataLoadContext
In .NET Core, Assembly.ReflectionOnlyLoadFrom()
is not supported and will throw a System.PlatformNotSupportedException
. Instead, you can use System.Reflection.Metadata.MetadataReader
or System.Reflection.MetadataLoadContext
. Below are examples of how to utilize each.
For example, Using MetadataReader
MetadataReader
allows you to read the metadata of an assembly without fully loading it.
using System.Reflection.Metadata; using System.Reflection.PortableExecutable; var assemblyPath = @"C:\Projects\BackgroundLogger\bin\Debug\net5.0\BackgroundLogger.dll"; using (var sr = new StreamReader(assemblyPath)) { using (var portableExecutableReader = new PEReader(sr.BaseStream)) { var metadataReader = portableExecutableReader.GetMetadataReader(); foreach (var typeDefHandle in metadataReader.TypeDefinitions) { var typeDef = metadataReader.GetTypeDefinition(typeDefHandle); if (string.IsNullOrEmpty(metadataReader.GetString(typeDef.Namespace))) continue; // Skip if the namespace is empty, it's likely not a user-defined type if (typeDef.Attributes.HasFlag(TypeAttributes.Abstract) || !typeDef.Attributes.HasFlag(TypeAttributes.Public)) continue; // Skip non-public concrete types Console.WriteLine(metadataReader.GetString(typeDef.Name)); } } }
This will list all public, concrete user-defined types in the assembly:
MainClass Startup LoggerService LoggerConfig LoggingEnum LogStruct LogMessage LogRepository
This method doesn't differentiate between class, struct, or enum types. If you need to filter for classes only, additional logic is needed.
For example, Using MetadataLoadContext
MetadataLoadContext
provides another approach for reflection-only loading in .NET Core. It allows you to load assemblies and work with them using reflection APIs. First, install the System.Reflection.MetadataLoadContext
NuGet package with:
Install-Package System.Reflection.MetadataLoadContext
Then, use MetadataLoadContext
to extract type information from the assembly:
using System.Reflection; using System.Runtime.InteropServices; var assemblyPath = @"C:\Projects\BackgroundLogger\bin\Debug\net5.0\BackgroundLogger.dll"; var resolver = new PathAssemblyResolver(new List<string>(Directory.GetFiles(RuntimeEnvironment.GetRuntimeDirectory(), "*.dll")) { assemblyPath }); using (var metadataContext = new MetadataLoadContext(resolver)) { Assembly assembly = metadataContext.LoadFromAssemblyPath(assemblyPath); foreach (var type in assembly.GetTypes()) { if (type.IsPublic) { Console.WriteLine(type.Name); } } }
This will print the names of all public types in the assembly:
MainClass Startup LoggerService ILoggerService LogRepository LogMessage LogController
While ReflectionOnlyLoadFrom()
works well in .NET Framework, you'll need to rely on MetadataReader
or MetadataLoadContext
in .NET Core for reflection-only loading. Each of these techniques provides a way to inspect assemblies for type metadata without fully loading them into memory, avoiding the potential for runtime errors.
- Using the OrderBy and OrderByDescending in LINQ
- Querying with LINQ
- Optimizing Performance with Compiled Queries in LINQ
- MinBy() and MaxBy() Extension Methods in .NET
- SortBy, FilterBy, and CombineBy in NET 9
- Exploring Hybrid Caching in .NET 9.0
- Using Entity Framework with IDbContext in .NET 9.0
- Primitive types in C#