-1

I have following classes in the C# Library assembly.

public static class TestClass
{
    static int counter = 0;
    static TestClass()
        {
            System.Diagnostics.Debug.Print("TestLibrary.TestClass is constructed...");
        }

        public static void Say()
        {
            System.Diagnostics.Debug.Print($"TestClass.Say called {counter++} times");
        }
}

[Serializable]
public class TestLibraryProxy
{
    static int _executionCount = 0;
        public void Execute()
        {
            System.Diagnostics.Debug.Print($"TestLibraryProxy Execute [{_executionCount++}]");
            TestClass.Say();
            TestClass.Say();
        }
}

From another C# application I am trying to load the above assembly into a application domain and call the TestLibraryProxy.Execute() method.

class Program
{
    static void Main(string[] args)
    {
        CreateAppDomainAndCallStaticMethod("MyDomain1");
        CreateAppDomainAndCallStaticMethod("MyDomain2");
        CreateAppDomainAndCallStaticMethod("MyDomain3");
        CreateAppDomainAndCallStaticMethod("MyDomain4");
    }

    private static void CreateAppDomainAndCallStaticMethod(string domainName)
    {
        AppDomain domain = AppDomain.CreateDomain(domainName);
        var k = domain.CreateInstanceAndUnwrap("TestLibrary", typeof(TestLibraryProxy).FullName) as TestLibraryProxy;
        k.Execute();
        AppDomain.Unload(domain);
    }
}
Output
TestLibraryProxy Execute [0]
TestLibrary.TestClass is constructed...
TestClass.Say called 0 times
TestClass.Say called 1 times
TestLibraryProxy Execute [1]
TestClass.Say called 2 times
TestClass.Say called 3 times
TestLibraryProxy Execute [2]
TestClass.Say called 4 times
TestClass.Say called 5 times
TestLibraryProxy Execute [3]
TestClass.Say called 6 times
TestClass.Say called 7 times

I have noticed that static counters value in the TestClass is getting retained across app domains. This value is getting retained even if I load and unload the app domain multiple times.

I have read that static variables are stored at Application Domain level. But looks like it is not true? Any idea how CLR is managing the static data across Application Domains.

Vijay
  • 513
  • 1
  • 6
  • 16
  • Possible duplicate of [Difference between Serializable and MarshalByRefObject](https://stackoverflow.com/questions/19315786/difference-between-serializable-and-marshalbyrefobject) – mjwills Jun 04 '18 at 06:20
  • Did that help @Vijay? – mjwills Jun 05 '18 at 01:31

1 Answers1

4

This is because TestLibraryProxy has been marked [Serializable].

Instead, it should inherit from MarshalByRefObject.

Basically what you have done is create an object in another AppDomain then copied (serialised) it into the original AppDomain. Using MarshalByRefObject avoids that. It ensures the object is not copied - instead you will be dealing with a reference to the original object (running in a different AppDomain).

If you make that change

public class TestLibraryProxy : MarshalByRefObject

the output changes to:

TestLibraryProxy Execute [0]
TestLibrary.TestClass is constructed...
TestClass.Say called 0 times
TestClass.Say called 1 times

repeated multiple times

mjwills
  • 23,389
  • 6
  • 40
  • 63