Reflection: Create instance of a class that inherit from another class located in separate assembly
I created an empty web form application that run under .Net Framework 4.7.2
and created a webform and a class named MyClass
:
namespace WebApplication1
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
public string GetText()
{
return "Message of Web Form 1";
}
}
}
and:
namespace WebApplication1
{
public class MyClass
{
public string GetText()
{
return "Message from MyClass";
}
}
}
and I publish it using "Merge all assemblies in one assembly" option:
Then I want to get type and then create instance of WebForm1
and MyClass
.
I wrote this code in a console application that run under .Net 5
:
Assembly asm = Assembly.LoadFrom(@"C:\Pub\bin\WebApplication1.dll");
Type tMyClass = asm.GetType("WebApplication1.MyClass");
Type t = asm.GetType("WebApplication1.WebForm1"); <----Error
After the code has run, tMyClass
has the correct type:
]
but when I try to get the type of WebForm1
, I get an error:
System.TypeLoadException: 'Could not load type 'System.Web.UI.Page' from assembly 'System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.'
How can I get type of WebForm1
and create an instance of it?
Solution 1:
The reason for the error is because System.Web.UI.Page
does not exist in .NET 5. So you can't load the assembly for the purpose of executing the code within your console app.
However, you can still load the metadata of your class WebApplication1.WebForm1
in a reflection-only context for the purpose of examining the type. The way you do it in .NET 5 is different than .NET Framework by using a MetadataLoadContext
from this NuGet package.
var dllPath = @"C:\Pub\bin\WebApplication1.dll";
var paths = new List<string>();
paths.AddRange(Directory.GetFiles(Path.GetDirectoryName(dllPath), "*.dll"));
paths.AddRange(Directory.GetFiles(RuntimeEnvironment.GetRuntimeDirectory(), "*.dll"));
using var context = new MetadataLoadContext(new PathAssemblyResolver(paths));
var asm = context.LoadFromAssemblyPath(dllPath);
var yourType = asm.GetType("WebApplication1.WebForm1");
Also note, if you're trying to access the methods that are defined in a not loaded assembly, you will still get error:
yourType.GetMethods(); // Error
yourType.GetMethods(BindingFlags.DeclaredOnly); // OK
Solution 2:
You load an assembly built in .NET Framework
via reflection on .NET Core
, but some of the classes in System.Web
namespace are not supported in .NET Core
. It load user code parts. And other parts may not work. In your case the requested class of the code compiled for .NET Framework
is not part of .NET Core
.
System.Web
is for Asp.Net
and in .NET Core
the System.Web
namespace exists and could technically be called but it won't work like you want.