Campos estáticos en AppDomain

Estoy experimentando ideas sobre el uso de AppDomain para administrar algún código heredado que contiene muchos campos estáticos en un entorno de subprocesos múltiples.

Leí esta pregunta: ¿Cómo usar un dominio de aplicación para limitar el scope de una clase estática para uso seguro de subprocesos? , pensé que era bastante prometedor y decidí probarlo con una clase muy simple en el ensamblado ClassLibrary1.dll:

namespace ClassLibrary1 { public static class Class1 { private static int Value = 0; public static void IncrementAndPrint() { Console.WriteLine(Value++); } } } 

y aquí está mi código que carga el ensamblado en 2 dominios de aplicación diferentes e invoca IncrementAndPrint () varias veces:

 var appDomain1 = System.AppDomain.CreateDomain("AppDomain1"); var appDomain2 = System.AppDomain.CreateDomain("AppDomain2"); var assemblyInAppDomain1 = appDomain1.Load("ClassLibrary1"); var assemblyInAppDomain2 = appDomain2.Load("ClassLibrary1"); var class1InAppDomain1 = assemblyInAppDomain1.GetType("ClassLibrary1.Class1"); var class1InAppDomain2 = assemblyInAppDomain2.GetType("ClassLibrary1.Class1"); class1InAppDomain1.InvokeMember("IncrementAndPrint", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null); class1InAppDomain1.InvokeMember("IncrementAndPrint", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null); class1InAppDomain1.InvokeMember("IncrementAndPrint", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null); class1InAppDomain2.InvokeMember("IncrementAndPrint", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null); class1InAppDomain2.InvokeMember("IncrementAndPrint", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null); class1InAppDomain2.InvokeMember("IncrementAndPrint", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null); 

Esperaba que la salida fuera:

 0 1 2 0 1 2 

porque habrá una copia del campo estático Value en local para cada instancia de AppDomain. Sin embargo, en cambio, lo que obtuve fue:

 0 1 2 3 4 5 

lo que me dice que todavía comparten la misma copia del valor del campo estático. ¿Alguien puede decirme qué he hecho mal aquí?

Actualizar:

Probé la sugerencia de Erik, ahora llamo al método CreateInstanceAndUnwrap () de la clase AppDomain en lugar de llamar a Load () y GetType () como se muestra a continuación. Además, he convertido IncrementAndPrint a un método de instancia en lugar de a un método estático. Sin embargo, sigo obteniendo el mismo resultado.

 var appDomain1 = System.AppDomain.CreateDomain("AppDomain1"); var appDomain2 = System.AppDomain.CreateDomain("AppDomain2"); var class1InAppDomain1 = (Class1)appDomain1.CreateInstanceAndUnwrap("ClassLibrary1", "ClassLibrary1.Class1"); var class1InAppDomain2 = (Class1)appDomain2.CreateInstanceAndUnwrap("ClassLibrary1", "ClassLibrary1.Class1"); class1InAppDomain1.IncrementAndPrint(); class1InAppDomain1.IncrementAndPrint(); class1InAppDomain1.IncrementAndPrint(); class1InAppDomain2.IncrementAndPrint(); class1InAppDomain2.IncrementAndPrint(); class1InAppDomain2.IncrementAndPrint(); 

Parece que estás cargando un tipo de otro appDomain en el appDomain actual. Por lo tanto, el código que llama a los métodos estáticos llama desde el dominio de la aplicación actual.

No conozco ninguna otra forma de llamar a un método estático en otro dominio sin crear una instancia de un objeto en otro dominio, y hacer que ese objeto llame al método estático.

Ejemplo: La solución contiene 2 proyectos (ClassLibrary y una aplicación Winforms / Console)

[ClassLibrary]

 using System; namespace MyLibrary { public class DomainObject : MarshalByRefObject { private static int _Value; private static void IncrementValue() { DomainObject._Value++; } public static int Value { get { return DomainObject._Value; } } public int GetIncrementedValue() { DomainObject.IncrementValue(); return DomainObject.Value; } } } 

[Solicitud]

 private void button1_Click(object sender, EventArgs e) { AppDomain domain1 = AppDomain.CreateDomain("domain1"); AppDomain domain2 = AppDomain.CreateDomain("domain2"); DomainObject object1 = domain1.CreateInstanceAndUnwrap("MyLibrary", "MyLibrary.DomainObject") as DomainObject; DomainObject object2 = domain2.CreateInstanceAndUnwrap("MyLibrary", "MyLibrary.DomainObject") as DomainObject; if (object1 != null) { Console.WriteLine("object 1 Value = " + object1.GetIncrementedValue().ToString()); Console.WriteLine("object 1 Value = " + object1.GetIncrementedValue().ToString()); Console.WriteLine("object 1 Value = " + object1.GetIncrementedValue().ToString()); } if (object2 != null) { Console.WriteLine("object 2 Value = " + object2.GetIncrementedValue().ToString()); Console.WriteLine("object 2 Value = " + object2.GetIncrementedValue().ToString()); Console.WriteLine("object 2 Value = " + object2.GetIncrementedValue().ToString()); } /* Unload the Domain and re-create * This should reset the Static Value in the AppDomain */ AppDomain.Unload(domain1); domain1 = AppDomain.CreateDomain("domain1"); object1 = domain1.CreateInstanceAndUnwrap("MyLibrary", "MyLibrary.DomainObject") as DomainObject; if (object1 != null) { Console.WriteLine("object 1 Value = " + object1.GetIncrementedValue().ToString()); Console.WriteLine("object 1 Value = " + object1.GetIncrementedValue().ToString()); Console.WriteLine("object 1 Value = " + object1.GetIncrementedValue().ToString()); } if (object2 != null) { Console.WriteLine("object 2 Value = " + object2.GetIncrementedValue().ToString()); Console.WriteLine("object 2 Value = " + object2.GetIncrementedValue().ToString()); Console.WriteLine("object 2 Value = " + object2.GetIncrementedValue().ToString()); } } 

Resultados generados:

 object 1 Value = 1 object 1 Value = 2 object 1 Value = 3 object 2 Value = 1 object 2 Value = 2 object 2 Value = 3 object 1 Value = 1 object 1 Value = 2 object 1 Value = 3 object 2 Value = 4 object 2 Value = 5 object 2 Value = 6