Unable to unload and reload assembly when loading more than one
antopilo opened this issue · 2 comments
antopilo commented
It used to not be possible to unload/load an assembly since the reflection improvements.
It works fine when you load 1 assembly and unload it. But doesnt seem to work properly when you load more than 1 assembly and unload them and reload them.
You get the same exception as before:
Unhandled native exception: System.Reflection.TargetException: Object does not match target type.
at System.Reflection.MethodBase.ValidateInvokeTarget(Object target)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at Coral.Managed.ManagedObject.InvokeMethod(IntPtr InObjectHandle, NativeString InMethodName, IntPtr InParameters, ManagedType* InParameterTypes, Int32 InParameterCount)
This is how I am loading my assemblies:
_LoadContext = m_HostInstance->CreateAssemblyLoadContext(m_ContextName);
// Load Nuake assembly DLL
const std::string absoluteAssemblyPath = FileSystem::Root + m_NetDirectory + "/" + m_EngineAssemblyName;
m_NuakeAssembly = m_LoadContext.LoadAssembly(absoluteAssemblyPath);
// Upload internal calls for each module
// --------------------------------------------------
for (const auto& netModule : m_Modules)
{
const std::string inClassName = m_Scope + '.' + netModule->GetModuleName();
for (const auto& [methodName, methodPtr] : netModule->GetMethods())
{
m_NuakeAssembly.AddInternalCall(inClassName, methodName, methodPtr);
}
}
m_NuakeAssembly.UploadInternalCalls();
m_GameAssembly = m_LoadContext.LoadAssembly(absoluteGameAssemblyPath);
// Detecting entity scripts
for (auto& type : m_GameAssembly.GetTypes())
{
Logger::Log(std::string("Detected type: ") + std::string(type->GetName()), ".net");
Logger::Log(std::string("Detected base type: ") + std::string(type->GetBaseType().GetName()), ".net");
const std::string baseTypeName = std::string(type->GetBaseType().GetName());
if (baseTypeName == "Entity")
{
// We have found an entity script.
m_GameEntityTypes[std::string(type->GetName())] = type;
}
}
This is how I am unloading:
for (auto& [entity, managedObject] : m_EntityToManagedObjects)
{
managedObject.Destroy();
}
m_GameEntityTypes.clear();
Coral::GC::Collect();
m_HostInstance->UnloadAssemblyLoadContext(m_LoadContext);
m_EntityToManagedObjects.clear();
peter1745 commented