116 votes

Comment Charger assemblée domaine d'application avec toutes les références de manière récursive?

Je veux charger à nouveau AppDomin certains assemblée qui a un complexe de références de l'arbre (MyDll.dll -> Microsoft.Office.Interop.Excel.dll -> Microsoft.Vbe.Interop.dll -> Office.dll -> stdole.dll)

Que j'ai compris, lorsqu'une assemblée est chargé de domaine d'application, les références ne serait pas chargé automatiquement, et je dois les charger manuellement. Alors, quand je fais:

string dir = @"SomePath"; // different from AppDomain.CurrentDomain.BaseDirectory
string path = System.IO.Path.Combine(dir, "MyDll.dll");

AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
setup.ApplicationBase = dir;
AppDomain domain = AppDomain.CreateDomain("SomeAppDomain", null, setup);

domain.Load(AssemblyName.GetAssemblyName(path));

et got FileNotFoundException:

Impossible de charger le fichier ou l'assembly 'Madll, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' ou une de ses dépendances. Le système ne peut pas trouver le fichier spécifié.

Je pense que le mot clé est l'une de ses dépendances.

Ok, je le fais avant l' domain.Load(AssemblyName.GetAssemblyName(path));

foreach (AssemblyName refAsmName in Assembly.ReflectionOnlyLoadFrom(path).GetReferencedAssemblies())
{
    domain.Load(refAsmName);
}

Mais j'ai reçu FileNotFoundException encore une fois, sur un autre (de référence) de l'assemblée.

Comment charger toutes les références de manière récursive?

Dois-je créer des références de l'arbre avant le chargement de la racine de l'assemblée? Comment obtenir un assemblage de références sans le charger?

70voto

Jduv Points 419

Vous avez besoin d'invoquer CreateInstanceAndUnwrap avant votre proxy de l'objet s'exécute dans le étrangères domaine d'application.

 class Program
{
    static void Main(string[] args)
    {
        AppDomainSetup domaininfo = new AppDomainSetup();
        domaininfo.ApplicationBase = System.Environment.CurrentDirectory;
        Evidence adevidence = AppDomain.CurrentDomain.Evidence;
        AppDomain domain = AppDomain.CreateDomain("MyDomain", adevidence, domaininfo);

        Type type = typeof(Proxy);
        var value = (Proxy)domain.CreateInstanceAndUnwrap(
            type.Assembly.FullName,
            type.FullName);

        var assembly = value.GetAssembly(args[0]);
        // AppDomain.Unload(domain);
    }
}

public class Proxy : MarshalByRefObject
{
    public Assembly GetAssembly(string assemblyPath)
    {
        try
        {
            return Assembly.LoadFile(assemblyPath);
        }
        catch (Exception)
        {
            return null;
            // throw new InvalidOperationException(ex);
        }
    }
}

Aussi, notez que si vous utilisez LoadFrom , vous obtiendrez probablement un FileNotFound d'exception parce que l'Assemblée résolveur va tenter de trouver l'assemblage que vous êtes en train de charger dans le cas ou l'actuel dossier bin de l'application. Utiliser LoadFile à la charge de l'arbitraire d'un fichier d'assemblage au lieu-mais notez que si vous faites cela, vous aurez besoin de charger les dépendances vous-même.

13voto

user1996230 Points 377

http://support.microsoft.com/kb/837908/en-us

Version C#

Créer un modérateur de classe et d'héritage de MarsharByRef

class ProxyDomain : MarshalByRefObject
{
    public Assembly GetAssembly(string AssemblyPath)
    {
        try
        {
            return Assembly.LoadFrom(AssemblyPath);
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException(ex);
        }
    }
}

appel à partir du site client

ProxyDomain pd = new ProxyDomain();
Assembly assembly = pd.GetAssembly(assemblyFilePath);

13voto

Nir Points 81

Une fois que vous passez l'assemblée instance à l'appelant de domaine, le domaine appelant vais essayer de la charger! C'est pourquoi vous obtenez une exception. (Ce qui se passe dans votre dernière ligne de code

domain.Load(AssemblyName.GetAssemblyName(path));

Donc, tout ce que vous voulez faire avec l'assemblée, devrait être fait dans une classe proxy - une classe qui hérite de MarshalByRefObject.

Prendre en compte que le domaine appelant et le nouveau domaine doit à la fois avoir accès à la classe de proxy de l'assemblée. Si votre problème n'est pas trop compliqué, envisager de quitter la ApplicationBase dossier inchangée, de sorte qu'il sera le même que le domaine appelant dossier (le nouveau nom de domaine ne charge que les Assemblées dont elle a besoin).

Dans code simple:

public void DoStuffInOtherDomain()
{
    const string assemblyPath = @"[AsmPath]";
    var newDomain = AppDomain.CreateDomain("newDomain");
    var asmLoaderProxy = (ProxyDomain)newDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(ProxyDomain).FullName);

    var loaderAsm = asmLoaderProxy.GetType().GetMethod("GetAssembly");
    loaderAsm.Invoke(asmLoaderProxy, new object[] { assemblyPath });
}

class ProxyDomain : MarshalByRefObject
{
    public void GetAssembly(string AssemblyPath)
    {
        try
        {
            Assembly.LoadFrom(AssemblyPath);
            //If you want to do anything further to that assembly, you need to do it here.
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException(ex.Message, ex);
        }
    }
}

11voto

David Points 20209

Sur votre nouveau domaine d'application, essayez de définir une AssemblyResolve gestionnaire d'événement. Cet événement est appelé lorsqu'une dépendance est manquante.

5voto

Dustin Campbell Points 6323

Vous devez gérer le domaine d'application.AssemblyResolve ou domaine d'application.ReflectionOnlyAssemblyResolve événements (en fonction de la charge que vous faites) dans le cas où l'assembly référencé n'est pas dans le GAC ou sur le CLR s de sondage chemin.

Domaine d'application.AssemblyResolve

Domaine d'application.ReflectionOnlyAssemblyResolve

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X