2010-06-30 4 views
2

J'essaie de personnaliser le processus de résolution d'assemblage en enveloppant le AppDomain et son événement AssemblyResolve dans une classe. La version simplifiée de mon ClassLoader est ci-dessous. Le problème que j'ai est que lorsque l'événement AssemblyResolve est déclenché, il semble que je reçois une nouvelle instance de ClassLoader, pas celle que j'ai créée précédemment.Problèmes avec l'événement AssemblyResolve sur AppDomain créé

[Serializable] 
public class ClassLoader // : IDisposable 
{ 
    public AppDomain Domain { get; private set; } 
    public string FooProperty { get; set; } 

    public ClassLoader(string domain) { 
     Domain = AppDomain.CreateDomain(domain); 
     Domain.AssemblyResolve += Domain_AssemblyResolve; 
    } 

    private Assembly Domain_AssemblyResolve(object sender, ResolveEventArgs args) 
    { 
     Console.WriteLine(
      "ClassLoader HashCode: {0} FooProperty: {1}\n\n", 
      GetHashCode(), 
      FooProperty); 
     // ... 
     return null; 
    } 
    // ... 
} 

Lors de l'exécution de ce code, FooProperty n'est pas initialisé dans le gestionnaire d'événements Domain_AssemblyResolve et l'instance de ClassLoader a un code de hachage différent de "c".

var c = new ClassLoader("demo"); 
c.FooProperty = "Foo"; 
Console.WriteLine(
    "c Hash Code: {0} FooProperty: {1}", 
    c.GetHashCode(), 
    c.FooProperty); 
c.Domain.CreateInstanceAndUnwrap("Not important", "Not important"); 

Que faites-vous? ou une solution de contournement?

Merci!

Répondre

2

Le ClassLoader exemple c est créé sur le domaine d'application A et puisqu'il ne hérite pas de MarshalByRefObject il sera sérialisé dans le domaine d'application que vous créez au moment où vous ajoutez le gestionnaire d'événements à AssemblyResolve. Cela se produit car la méthode est une méthode d'instance et le délégué aura besoin d'une référence à l'objet cible où la méthode sera appelée. Si vous souhaitez simplement que les FooProperty aient une valeur spécifique lorsque le gestionnaire d'événements est déclenché, vous pouvez ajouter le gestionnaire d'événements uniquement après l'initialisation de la propriété, ce qui entraîne la sérialisation de la valeur et sa disponibilité dans le domaine d'application nouvellement créé.

public string FooProperty { get; private set; } 

public ClassLoader(string domain, string fooProperty) 
{ 
    FooProperty = fooProperty; // Set it before adding event handler 
    Domain = AppDomain.CreateDomain(domain); 
    Domain.AssemblyResolve += Domain_AssemblyResolve; 
} 

Si vous avez l'exigence que l'instance c est disponible dans les deux domaines d'application, alors vous devriez jeter un oeil à:

Making Objects Remotable

Events and Delegates with .NET Framework Remoting

0

Eh bien,

Lors de l'exécution de ce code, FooProperty n'est pas initialisé en cas Domain_AssemblyResolve

Il ne semble pas y avoir de code qui initialise Foo dans le gestionnaire.

l'instance ClassLoader a un code de hachage différent de de "c".

Les instances de classes qui héritent de l'objet (comme ClassLoader) et ne réimplémentez GetHashCode(), comme dans votre cas, auront tous différents codes de hachage (en fonction de l'adresse de l'objet). Remplacez GetHashCode() si vous voulez des codes cohérents basés sur l'état interne.

Questions connexes