c# .net appdomain

c# - Campos estáticos en AppDomain



.net (1)

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

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 alcance 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();