TheChilliPL TheChilliPL - 2 months ago 22
C# Question

Assembly.GetType("[...]", true); throws TypeLoadException

My code:

//App, Core.cs
using System;
using System.IO;
using System.Reflection;

namespace Game
{
public static void Main(string[] args)
{
Assembly a = Assembly.LoadFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "mods\\ExampleMod.dll"));
var x1 = a.GetType("PTF_Mod.Mod_Main");
var x2 = x1.GetMethod("OnStart");
var x3 = x2.Invoke(null, new object[] { });

while(true);
}
}


//App, ModCrew.cs
using System;
using System.Reflection;

namespace Engine
{
public static class ModCrew
{
public class Mod
{
public void ItWorks()
{
Console.WriteLine("It works!");
}
}
}
}

//DLL, Mod_Main.cs
using System;
using System.Reflection;

namespace PTF_Mod
{
public static class Mod_Main
{
public static void OnStart()
{
var exe = Assembly.GetCallingAssembly();
Console.WriteLine(exe.Location); //Location is valid
var x = exe.GetType("Engine.ModCrew.Mod", true); //But here I get exception
var y = Activator.CreateInstance(x);

x.GetMethod("ItWorks", BindingFlags.Instance).Invoke(null, object[] { });
}
}
}


Exception:
An exception of type 'System.TypeLoadException' occurred in mscorlib.dll but was not handled in user code

Additional information: Nie można załadować typu 'Engine.ModCrew.Mod' z zestawu 'Game, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.

Answer

You should always use BindingFlags when getting methods via reflection.

Invoking an instance with MethodInfo.Invoke requires the instance as the first parameter MethodInfo.Invoke(MyInstance,...)

Changes based on comments:

public static void Main(string[] args)
{
    Assembly a = Assembly.LoadFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "mods\\ExampleMod.dll"));
    var x1 = a.GetType("PTF_Mod.Mod_Main");
    var x2 = x1.GetMethod("OnStart", BindingFlags.Static | BindingFlags.Public);
    var x3 = x2.Invoke(null, null);

    while(true);
}

Mod_Main:

public static void OnStart()
{
    var exe = Assembly.GetCallingAssembly();
    Console.WriteLine(exe.Location); //Location is valid
    var x = exe.GetType("Engine.ModCrew+Mod", true); //But here I get exception
    var y = Activator.CreateInstance(x);

    x.GetMethod("ItWorks", BindingFlags.Instance | BindingFlags.Public).Invoke(y, null);
}

Also, consider if reflection is even necessary, it can make programs overly complicated. If it's necessary you should look into Dynamic to avoid a lot of the troubles of invoking methods with reflection