Dans le cadre d'un projet sur lequel je travaille, je crée un fichier AppDomain
et lui demande de charger l'assemblage en cours d'exécution. J'invoque ensuite Activator.CreateInstanceFrom
pour créer une instance marshallisée d'une classe interne (de type MyType
) en tant que tel (et vous pouvez voir qu'il utilise également le même emplacement d'assemblage) :
ObjectHandle handle = Activator.CreateInstanceFrom(
Factory.operatingDomain,
Assembly.GetExecutingAssembly().Location,
typeof(MyType).FullName,
false,
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new object[] { config },
null,
null);
Tout fonctionne correctement lorsque je teste cet assemblage à l'unité, mais lorsque je l'utilise dans un environnement de débogage ASP.NET, il génère une erreur de type MissingMethodException
. J'ai pris le temps de créer ma propre classe qui étend le concept de Binder
pour voir ce qui se passe. La seule différence semble être que dans l'environnement de débogage, le paramètre passé ( config
) tire son type de l'assemblage situé dans le répertoire habituel, tandis que l'élément ParameterInfo
obtient son type de l'assembly situé dans le dossier temporaire ASP.NET.
Même si j'ai réussi typeof(config).Assembly.Location
J'obtiendrais le même résultat. Il s'agit donc de quelque chose d'interne au cadre.
Y a-t-il quelque chose que je puisse faire pour corriger cela, à part conserver un classeur personnalisé accessible en interne et destiné à une utilisation de niche, qui renvoie la valeur "true" lorsque les types de paramètres correspondent conformément à la norme FullName
?
MISE À JOUR
J'ai essayé de passer l'emplacement de l'assemblage tel qu'il est pris dans les assemblages chargés du domaine de l'application et toujours pas de dés. Mon binder personnalisé n'a pas fonctionné non plus - il m'a fallu implémenter Binder.ChangeType où j'ai découvert que je ne pouvais même pas passer d'un type à l'autre (même si, comme indiqué, la seule différence entre eux est l'emplacement de l'assemblage).
MISE À JOUR 2
J'ai essayé le code suivant pour m'assurer que le domaine d'application chargeait l'assemblage approprié à partir de l'emplacement adéquat :
if (binPath != String.Empty)
{
Factory.operatingDomain.SetData("assemblyLocation", Assembly.GetExecutingAssembly().Location);
Factory.operatingDomain.DoCallBack(() =>
{
String location = AppDomain.CurrentDomain.GetData("assemblyLocation").ToString();
String filename = System.IO.Path.GetFileName(location);
List<String> paths = AppDomain.CurrentDomain.RelativeSearchPath.Split(';').ToList();
foreach (String path in paths.ToArray())
{
paths.Remove(path);
paths.AddRange(System.IO.Directory.GetFiles(path, filename));
}
Assembly.LoadFrom(paths[0]);
});
}
Et c'est vrai ! Il a chargé le bon assemblage ! Mais ici, juste un peu plus tard :
String location = Factory.operatingDomain
.GetAssemblies()
.Single(a => a.FullName == Assembly.GetExecutingAssembly().FullName)
.Location;
Ceci renvoie le chemin du dossier temporaire .NET. Ce n'est pas correct. Je considère qu'il s'agit d'un bogue dans le cadre de travail !