2012-03-21 6 views
21

mamStatyczne Variable Instances i AppDomains, co się dzieje?

public static class A 
{ 
    public static string ConnString; 
} 

[Serializable] 
public class Test{ 
    // Accesing A's field; 
    public string ConnString{get{return A.ConnString;}set{A.ConnString=value;}} 
} 

void Main() 
{ 
    A.ConnString = "InitialString"; // I set A.ConnString in the current domain 

    var newDomain = AppDomain.CreateDomain("DomNew"); 
    Test TObj = newDomain.CreateInstanceAndUnwrap(typeof(Test).Assembly.FullName, typeof(Test).FullName) as Test ; 

    TObj.ConnString = "NewDomainString"; // It is supposed to set A.ConnString in the newDomain aka a different instance of A.ConnString 

    // Here it is supposed to print two different values 
    Console.WriteLine(A.ConnString); // "InitialString" 
    Console.WriteLine(TObj.ConnString); // "NewDomainString" 
} 

Ale NIE! Dwie linie zapisu, wydrukuj tę samą wartość "NewDomainString"! DLACZEGO ???

ten kod

TObj.ConnString = "NewDomainString" 

ma zmienić ciąg w nowo utworzonej domeny, ale wydaje się, że oba odnoszą się do tej samej instancji!

Dlaczego, co się tutaj dzieje?

+6

Prawdopodobny duplikat http://stackoverflow.com/questions/4298913/static-fields-in-appdomain – daryal

+2

Proszę nie zamieniać tytułów na "C#" i tym podobne. Po to są tagi. –

+0

Masz rację John! Newbie tutaj :) Uczę się! Dzięki! –

Odpowiedz

21

Istnieją tylko dwa sposoby, aby klasa była dostępna z innego elementu AppDomain - jedna z nich to klasa [Serializable], tak jak klasa testowa, druga to klasa dziedzicząca po MarshalByRefObject. Ponieważ twoja klasa ma serializowalność, jej kopia jest tworzona dla każdego połączenia między aplikacjami. Więc Test że głównym AppDomain wystąpią podczas rozmowy ...

Test TObj = newDomain.CreateInstanceAndUnwrap(typeof(Test).Assembly.FullName, typeof(Test).FullName) as Test; 

faktycznie nie instancja testowy, który został stworzony w „DomNew” AppDomain- jest to kopia lokalna w „głównym” AppDomain i dlatego odwołuje się do zmiennych statycznych z "głównej" AppDomain.

Jeśli chcesz, aby Test pokazywał zachowanie, którego oczekujesz, uczyń go dziedziczącym z MarshalByRefObject, zamiast być Serializowalnym.

+1

Nit: faktycznie jest trzecia droga. marszałek przez krwawienie http://www.bluebytesoftware.com/blog/PermaLink,guid,884ca8af-76fb-4753-a9d9-d12075dabb51.aspx – JaredPar

+0

@JaredPar yikes, yeah ... Sprawia, że ​​się skrzywię. –

+0

Thanx, to było to, czego szukałem. Zdarzyło mi się, że znalazłem odpowiedź na własną rękę wkrótce po tym, jak zadałem pytanie. Z jakiegoś powodu nie próbowałem dziedziczenia MarshalByRef, chociaż wiedziałem, że coś takiego istnieje. Myślę, że zostałem wprowadzony w błąd przez odpowiedź na innym forum mówiąc, że te dwa sposoby (Serializable Attribute i MarshalByRef dziedziczenie) były identyczne. Chociaż sądzę, że jeśli Serializable Attirbute jest sposobem na "lokalną" kopię klasy, to faktycznie nie uzyskujesz dostępu do obiektu z innej domeny, prawda? Czy jest to po prostu "odczytanie" stanu obiektu z innej domeny? –

12

Oznaczyłeś swoją klasę Test jako Serializable. To jest źle. Powinieneś pochodzić od MarshalByRef. W przeciwnym razie TObj będzie po prostu lokalną kopią w bieżącym AppDomain.

+0

Zgadza się :) Dzięki stary! –