Proponuję zabawę z serii co zostanie wypisana na ekran. Mamy dwie klasy jak poniżej. Pierwsza z nich przekazywana jest pomiędzy domenami przez referencję, a druga przez wartość. Interfejs ITest ma charakter pomocniczy i nie ma znaczenia.
Obiekty przekazywane przez referencję wypiszą na ekran nazwę domeny w jakiej zostały utworzone. Nawet jeśli wywołanie jest inicjowane w innej domenie to zostanie przekazne do domeny orginalej ponieważ pracujemy z proxy do obiektu. W przypadku obiektów przekazywanych przez wartość na ekran zostanie wypisana nazwa domeny w jakiej następuje wywołanie.
Jeśli chodzi o wartość wypisaną na ekran to obiekty przekazywane przez referencję zawsze wypiszą ten sam wynik = 1 ponieważ zarówno wywołanie metody Start jak i odczyt Value dotyczy tego samego obiektu. W przypadku obiektów przekazywanych przez wartość w niektórych przypadkach możemy otrzymać zero. Stanie się tak kiedy wywołanie Start nastąpi w innej domenie niż ta, w której odczytujemy właściwość Value. A dzieje sie tak ponieważ obie czynność dotyczą de facto innych obiektów.
public interface ITest { int Value { get; set; } void Start(); } public class MarshalByRefObjectClass : MarshalByRefObject, ITest { public int Value { get; set; } public void Start() { Console.WriteLine(AppDomain.CurrentDomain.FriendlyName); Value++; } } [Serializable] public class MarshalByValueClass : ITest { public int Value { get; set; } public void Start() { Console.WriteLine(AppDomain.CurrentDomain.FriendlyName); Value++; } }Mamy również następujący kod, w którym testuję jak zachowuja się:
- Obiekty przekazywane przez wartość i przez referencję.
- Utworzone w bieżącej (przy pomocy konstruktora) oraz w innej domenie (przy pomocy AppDomain.CreateInstanceFromAndUnwrap).
- Przy wywołaniu na nich metody bezpośrednio oraz przy pomocy AppDomain.Callback.
private static void Test(AppDomain app, ITest test, bool doCallBack) { if (doCallBack) app.DoCallBack(test.Start); else test.Start(); Console.WriteLine(test.Value); }A to właściwy test, w którym najpierw tworzę obiekty przekazywane przez wartość/referencję lokalnie i w nowej domenie. Następnie wywołuję dla nich metodę Start i odczytuję właściwość Value.
var app = AppDomain.CreateDomain("TestDomain"); var asm = Assembly.GetExecutingAssembly(); var byRef = new MarshalByRefObjectClass(); var byRef1 = new MarshalByRefObjectClass(); var byRef2 = (MarshalByRefObjectClass)app.CreateInstanceFromAndUnwrap(asm.CodeBase, typeof(MarshalByRefObjectClass).FullName); var byRef3 = (MarshalByRefObjectClass)app.CreateInstanceFromAndUnwrap(asm.CodeBase, typeof(MarshalByRefObjectClass).FullName); var byValue = new MarshalByValueClass(); var byValue1 = new MarshalByValueClass(); var byValue2 = (MarshalByValueClass)app.CreateInstanceFromAndUnwrap(asm.CodeBase, typeof(MarshalByValueClass).FullName); var byValue3 = (MarshalByValueClass)app.CreateInstanceFromAndUnwrap(asm.CodeBase, typeof(MarshalByValueClass).FullName); Test(app, byRef, true); Test(app, byRef1, false); Test(app, byRef2, true); Test(app, byRef3, false); Test(app, byValue, true); Test(app, byValue1, false); Test(app, byValue2, true); Test(app, byValue3, false);Pytanie brzmi co zostanie wypisane na ekranie? Pokaż/Ukryj odpowiedź
Obiekty przekazywane przez referencję wypiszą na ekran nazwę domeny w jakiej zostały utworzone. Nawet jeśli wywołanie jest inicjowane w innej domenie to zostanie przekazne do domeny orginalej ponieważ pracujemy z proxy do obiektu. W przypadku obiektów przekazywanych przez wartość na ekran zostanie wypisana nazwa domeny w jakiej następuje wywołanie.
Jeśli chodzi o wartość wypisaną na ekran to obiekty przekazywane przez referencję zawsze wypiszą ten sam wynik = 1 ponieważ zarówno wywołanie metody Start jak i odczyt Value dotyczy tego samego obiektu. W przypadku obiektów przekazywanych przez wartość w niektórych przypadkach możemy otrzymać zero. Stanie się tak kiedy wywołanie Start nastąpi w innej domenie niż ta, w której odczytujemy właściwość Value. A dzieje sie tak ponieważ obie czynność dotyczą de facto innych obiektów.
Sandbox.vshost.exe 1 Sandbox.vshost.exe 1 TestDomain 1 TestDomain 1 TestDomain 0 Sandbox.vshost.exe 1 TestDomain 0 Sandbox.vshost.exe 1