Я пытаюсь создать систему с возможностью «горячей» замены, где пользователь может динамически загружать и выгружать DLL. Необходимо, чтобы основное приложение перезапустилось как можно меньше, поэтому я перемещаю как можно больше функциональности для внешних библиотек. Из каких исследований я выяснил, мне нужно создать второй AppDomain и загрузить DLL в это, а затем просто передать параметры и т. Д., Чтобы запустить его. В настоящее время, я считаю, что у меня большая часть работы с программой, но я сталкиваюсь с ошибкой при вызове функции AppDomain.Unwrap() объекта из CreateInstance. Ошибка заключается в следующем:C# AppDomain не может загрузить DLL
System.InvalidCastException: Unable to cast transparent proxy to type 'Program1.Loader'.
Вот код загрузки:
try {
unload(dom,out loader,true);
dom=null;
AppDomainSetup dms = new AppDomainSetup();
dms.ConfigurationFile=Environment.CurrentDirectory+Path.DirectorySeparatorChar+"Program1.exe.config";
dms.ApplicationBase=Environment.CurrentDirectory+Path.DirectorySeparatorChar+"Plugins";
Evidence ev = AppDomain.CurrentDomain.Evidence;
dom=AppDomain.CreateDomain("PluginManager",ev,dms);
AssemblyName an = AssemblyName.GetAssemblyName(Environment.CurrentDirectory+"\\Plugins\\PluginManager.dll");
ObjectHandle obj = dom.CreateInstance(an.FullName,"PluginManager.PluginManager");
loader = (Loader)obj.Unwrap();
loader.LoadAssembly(@"PluginManager.dll");
if(!suppressOutput)
Console.WriteLine("Reload successful.");
}
catch(Exception e) {
unload(dom,out loader,true);
loader=null;
Console.WriteLine("PluginManager failed loading. Enter \"reload\" to try again.\n");
Console.Write(e+"\n\n");
}
Эта линия, где выбрасывается ошибка:
loader = (Loader)obj.Unwrap();
внешней DLL практически не имеет код это, поскольку это является доказательством концепции. Он выглядит следующим образом:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PluginManager {
public class PluginManager:MarshalByRefObject {
public void run(string comm) {
Console.WriteLine(comm);
}
}
}
Редактировать: Вот код для класса загрузчика.
class Loader:MarshalByRefObject {
private Assembly _assembly;
public override object InitializeLifetimeService() {
return null;
}
public void LoadAssembly(string path) {
_assembly=Assembly.Load(AssemblyName.GetAssemblyName(path));
}
public object ExecuteStaticMethod(string typeName,string methodName,params object[] parameters) {
Type type = _assembly.GetType(typeName);
MethodInfo method = type.GetMethod(methodName,BindingFlags.Static|BindingFlags.Public);
return method.Invoke(null,parameters);
}
}
Я обновил код, чтобы включить загрузчик актеров. Не могли бы вы объяснить свой ответ с помощью небольшого кода? Я не уверен, что вы хотите, чтобы я сделал. – Bioniclegenius
Спасибо за редактирование! Но Loader находится в основной программе. Не сработает ли CreateInstance при попытке загрузить его из DLL? – Bioniclegenius
Но вы не пытаетесь загрузить Loader, вы пытаетесь загрузить PluginManager. Это проблема. Это то, что вы переходите в AppDomain.CreateInstance. –