Ma Dll sont chargées par l'application d'un tiers, on ne peut pas personnaliser. Mon assemblées doivent être situés dans leur propre dossier. Je ne peux pas les mettre dans le GAC (mon application doit être déployée à l'aide de la commande XCOPY). Lorsque la racine DLL essaie de charger des ressources ou de type DLL à partir d'un autre (dans le même dossier), le chargement échoue (fichier introuvable). Est-il possible d'ajouter le dossier où mon Dll sont situés à l'assemblée chemin de recherche par programme (à partir de la racine de la DLL)? Je ne suis pas autorisé à modifier les fichiers de configuration de l'application.
Réponses
Trop de publicités?On dirait que vous pouvez utiliser l'événement AppDomain.AssemblyResolve et charger manuellement les dépendances à partir de votre répertoire DLL.
Editer (à partir du commentaire):
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(LoadFromSameFolder);
static Assembly LoadFromSameFolder(object sender, ResolveEventArgs args)
{
string folderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll");
if (File.Exists(assemblyPath) == false) return null;
Assembly assembly = Assembly.LoadFrom(assemblyPath);
return assembly;
}
Vous pouvez ajouter un chemin de vérification au fichier .config de votre application, mais cela ne fonctionnera que si le chemin de vérification est contenu dans le répertoire de base de votre application.
Mise à jour de Framework 4
Depuis Framework 4 soulever le AssemblyResolve cas également pour les ressources effectivement ce gestionnaire fonctionne mieux. Il est basé sur le concept que les localisations sont, en application des sous-répertoires (un pour la localisation avec le nom de la culture, c'est à dire C:\MyApp\it pour l'italien) À l'intérieur il y a des ressources de fichier. Le gestionnaire fonctionne également si la localisation est pays-région, c'est à dire-il ou pt-BR. Dans ce cas, le gestionnaire d' "peut être appelé plusieurs fois: une fois pour chaque culture dans le repli de la chaîne" [à partir de MSDN]. Cela signifie que si nous retourner la valeur null pour les "il-elle" fichier de ressources le cadre déclenche l'événement en demandant "il".
Événement crochet
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(currentDomain_AssemblyResolve);
Gestionnaire d'événements
Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
//This handler is called only when the common language runtime tries to bind to the assembly and fails.
Assembly executingAssembly = Assembly.GetExecutingAssembly();
string applicationDirectory = Path.GetDirectoryName(executingAssembly.Location);
string[] fields = args.Name.Split(',');
string assemblyName = fields[0];
string assemblyCulture = fields[2].Substring(fields[2].IndexOf('=') + 1);
string assemblyFileName = assemblyName + ".dll";
string assemblyPath;
if (assemblyName.EndsWith(".resources"))
{
// Specific resources are located in app subdirectories
string resourceDirectory = Path.Combine(applicationDirectory, assemblyCulture);
assemblyPath = Path.Combine(resourceDirectory, assemblyFileName);
}
else
{
assemblyPath = Path.Combine(applicationDirectory, assemblyFileName);
}
if (File.Exists(assemblyPath))
{
//Load the assembly from the specified path.
Assembly loadingAssembly = Assembly.LoadFrom(assemblyPath);
//Return the loaded assembly.
return loadingAssembly;
}
else
{
return null;
}
}
La meilleure explication de MS elle - même :
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
private Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
//This handler is called only when the common language runtime tries to bind to the assembly and fails.
//Retrieve the list of referenced assemblies in an array of AssemblyName.
Assembly MyAssembly, objExecutingAssembly;
string strTempAssmbPath = "";
objExecutingAssembly = Assembly.GetExecutingAssembly();
AssemblyName[] arrReferencedAssmbNames = objExecutingAssembly.GetReferencedAssemblies();
//Loop through the array of referenced assembly names.
foreach(AssemblyName strAssmbName in arrReferencedAssmbNames)
{
//Check for the assembly names that have raised the "AssemblyResolve" event.
if(strAssmbName.FullName.Substring(0, strAssmbName.FullName.IndexOf(",")) == args.Name.Substring(0, args.Name.IndexOf(",")))
{
//Build the path of the assembly from where it has to be loaded.
strTempAssmbPath = "C:\\Myassemblies\\" + args.Name.Substring(0,args.Name.IndexOf(","))+".dll";
break;
}
}
//Load the assembly from the specified path.
MyAssembly = Assembly.LoadFrom(strTempAssmbPath);
//Return the loaded assembly.
return MyAssembly;
}