2009-04-22 9 views
1

Je le scénario suivant, à l'exception d'être jeté lorsque je tente de lancer:réflexion et casting

  1. J'ai ajouté une référence du projet et l'importation espace de noms du projet.
  2. La ligne LoadFile charge la DLL générée lors de la construction de ce projet.
  3. J'essaie d'accéder au champ public d'un attribut qui décore une propriété d'un objet de la DLL.
  4. Voici le texte d'exception:

[A] MyNamespace.PropertyMetaDataAttribute ne peut pas être jeté à [B] MyNamespace.PropertyMetaDataAttribute. Le type A provient de 'A, version = 12.0.0.25, Culture = neutre, PublicKeyToken = null' dans le contexte 'LoadFrom' à l'emplacement 'C: \ projectA \ bin \ debug \ A.dll'. Le type B provient de 'A, Version = 12.0.0.25, Culture = neutre, PublicKeyToken = null' dans le contexte 'Default' à l'emplacement 'C: \ currentProject \ bin \ debug \ A.dll'.

extrait de code:

using MyNamespace; // added project reference to this item 

m_Assembly = Assembly.LoadFile(ConfigurationManager.AppSettings["DLL_File_Path"]); 

Type objectType = m_Assembly.GetType(string.Format("{0}.{1}", NAMESPACE_PREFIX, "MyObject")); 

// Crash happens on line below: 

Attribute attr = (Attribute) objectType.GetProperty("Name").GetCustomAttributes(false)[0]; 

//This is the layout of the object which has the property 
MyObject 
{ 
    [MyAttribute(Name="FooName")] 
    Foo {get;set;} 
} 

// This is the definition of the attribute 
MyAttribute :Attribute 
{ 
    // Want to access the value 
    public string Name = string.Empty; 
} 

Répondre

4

Il semble que votre

ConfigurationManager.AppSettings["DLL_File_Path"] 

pointe au même dll dans un autre endroit, de sorte que le temps d'exécution .Net tente de charger une dll déjà chargé, Lorsque vous essayez de l'utiliser, le système de type explose à cause des types répétés entre les 2 dll ...

Selon l'erreur, t Hese sont les emplacements des deux

de dll
  • C: \ CurrentProject \ bin \ debug \ A.dll
  • C: \ projectA \ bin \ debug \ A.dll

Si la référence est explicitement défini sur la solution, vous pouvez essayer de définir la copie locale à False alors lorsque la solution génère, ne pas copier le résultat des dépendances

1

Si votre dll est déjà dans le chemin recherché automatiquement (répertoire actuel , bin etc), et chargé parce que vous avez référencé quelque chose dans cet assembly, votre LoadFile (vous voudrez peut-être utiliser LoadFrom à la place) chargera la même DLL dans un autre contexte (LoadFrom-context) au lieu de la valeur par défaut.

Vous devez soit envisager de charger la DLL une seule fois, soit tenter d'extraire d'abord votre assembly de votre contexte par défaut afin d'éviter le conflit, en consultant AppDomain.CurrentDomain.GetAssemblies().

Vous pouvez même attacher un gestionnaire d'événements AssemblyResolve à AppDomain.CurrentDomain en tant que solution de repli si vous essayez d'accéder à un assembly qui n'est pas dans le contexte par défaut.

http://msdn.microsoft.com/en-us/library/system.appdomain.assemblyresolve.aspx

AppDomain.CurrentDomain.GetAssemblies() contiendront des assemblées de tous les contextes, même ceux que vous avez chargé à l'aide LoadFrom/LoadFile.

1

Lorsque vous chargez un assembly, il existe différents contextes dans lesquels vous pouvez charger les types. C'est pourquoi vous ne pouvez pas passer d'un type à l'autre.Vous pouvez contourner ce problème en utilisant l'événement AssemblyResolve (comme le suggère jishi) ou il existe également un événement TypeResolve que vous pouvez utiliser pour renvoyer le type correct lorsque vous l'utilisez, mais je pense que vous devez simplement aligner l'assemblage sur bon contexte et de comprendre quand et comment il est chargé et ce qui est bon pour vous.

Ces articles du blog de Suzanne Cook m'ont vraiment aidé à comprendre les différents contextes et comment les choses sont chargées en eux et pourquoi.

http://blogs.msdn.com/suzcook/archive/2003/09/19/loadfile-vs-loadfrom.aspx

http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx

Aussi, si vous voulez regarder comment et pourquoi ils sont chargés, vous devriez regarder le Fusion logs avec eux ensemble pour vider toutes les informations sur et il vous montrera la charge informations pour l'assemblage.