Je tente de créer un système de plug-in remplaçable à chaud dans lequel l'utilisateur peut charger et décharger dynamiquement des DLL. Il est nécessaire que l'application de base redémarre le moins possible, donc je déplace à la place la plupart des fonctionnalités vers des bibliothèques externes. À partir de ce que j'ai découvert, j'ai besoin de créer un second AppDomain et de charger la DLL dans celui-ci, puis de simplement transmettre les paramètres et autres pour l'exécuter. Actuellement, je crois que la majeure partie du programme fonctionne, mais je rencontre une erreur lors de l'appel de la fonction AppDomain.Unwrap() sur l'objet à partir de CreateInstance. L'erreur est la suivante:C# AppDomain ne peut pas charger la DLL
System.InvalidCastException: Unable to cast transparent proxy to type 'Program1.Loader'.
Voici le code de chargement:
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");
}
Cette ligne est l'endroit où l'erreur est renvoyée:
loader = (Loader)obj.Unwrap();
La DLL externe n'a presque aucun code il, puisque c'est une preuve de concept. Il est comme suit:
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);
}
}
}
Modifier: Voici le code pour la classe loader.
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);
}
}
J'ai mis à jour le code pour inclure la distribution du chargeur. Pourriez-vous expliquer votre réponse avec un peu de code, s'il vous plaît? Je ne suis pas sûr de ce que tu veux que je fasse. – Bioniclegenius
Merci pour le montage! Mais Loader est dans le programme principal. Le CreateInstance échouerait-il quand il essaye de le charger de la DLL? – Bioniclegenius
Mais vous n'essayez pas de charger Loader, vous essayez de charger PluginManager. C'est le problème. C'est ce que vous passez à AppDomain.CreateInstance. –