none
A static class in a custom control RRS feed

  • Question

  • Just a question on the scope of a static class, consider this scenario:

    You have a client application, in this case a WPF application that has the capability to dynamically load assemblies as shown below.  The dynamic load method below is only called once, upon login.  That is, all assemblies in the dictionary are loaded up for use by the application later.  I have an assembly, actually a custom WPF control DLL, that is loaded in this fashion (as a byte array presented to the 'Assembly.Load()' method), and a static class within this assembly. 

    Now consider the document area of the WPF client application you are working with presents the content as tabitems in a tabcontrol object.  As the user switches from tabitem to tabitem, multiple instances of the custom control are created.  Although the custom control's assembly is loaded only once, the custom control itself is created and rendered multiple times, on multiple tabs.

    Here's the question; if the DLL which contains the custom control, also contains a static class, and the custom control is rendered multiple times, *I still only have one instance of the static class right*? 

    Follow up; how far can the static scope boundary extend?  I've read that it cannot extend passed the boundary of an AppDomain. 

    Thanks,

    Dan, MCP, MCTS

     public static StringCollection InitializeAssemblies(Dictionary<string,byte[]> assembliesAsByteArrays)  
            {  
                StringCollection initializationErrors = new StringCollection();  
     
                assemblies = new Dictionary<string,Assembly>();  
     
                if (assembliesAsByteArrays != null && assembliesAsByteArrays.Count > 0)  
                {  
                      
                    foreach(KeyValuePair<string, byte[]> assemblyPair in assembliesAsByteArrays )  
                    {  
                        try  
                        {  
                            Assembly customAssembly = Assembly.Load(assemblyPair.Value);  
                            assemblies.Add(assemblyPair.Key, customAssembly);  
                        }  
                        catch (Exception ex)  
                        {  
                            initializationErrors.Add(ex.Message);  
                        }  
                    }  
                }  
     
                return initializationErrors;  
            }  
     
     
    -DK
    Wednesday, December 17, 2008 3:54 PM

Answers

  • It actually has more to do with how the runtime handles assemblies than how it handles static classes. Assemblies can only be loaded into a single app-domain. If a process has two (or more) app domains defined, and an assembly gets loaded into the first app domain, the second app domain cannot see any details about the assembly that is loaded into app domain 1. It can't even access the classes or metadata defined in that assembly unless it also loads the assembly.

    And actually, you can create a quick test to prove this. Create a console app, and then add a class library to the solution. In the console app, create a reference to the class library. In the class library, create the following class:

    public class AppDomainController : MarshalByRefObject  
    {  
        private static Guid xxx = Guid.NewGuid();  
     
        public void WriteFile()  
        {  
            string path = @"C:\xxx_" + xxx.ToString("N") + ".txt";  
            File.WriteAllText(path, AppDomain.CurrentDomain.FriendlyName + " : " + xxx.ToString("N"));  
        }  

    Now, in the console app, create an instance of the appdomaincontroller class, and call writefile(). 

    AppDomainController a = new AppDomainController();
    a.WriteFile();

    This will create an instance and write a file to the C:\ folder. The name of the file will be based on the static GUID member. The contents of the file will give you the app domain name.

    Then, right below that code, create a new app domain, load the class library into it, and call the same method:

    AppDomain domain = AppDomain.CreateDomain("Domain2");
    AppDomainController b = (AppDomainController)domain.CreateInstanceFromAndUnwrap("ClassLibrary1.dll", "ClassLibrary1.AppDomainController");
    b.WriteFile();

    As you can see, when you run the console app, you end up with two files because the static GUID was initialized twice with different values, once for each app domain.
    -Rob Teixeira
    • Marked as answer by dotBomb Thursday, December 18, 2008 7:53 PM
    Thursday, December 18, 2008 5:31 PM

All replies

  • Actually, static classes have zero instances. Non-static classes allow you to create instances, which stamp out memory structures with the state of the objects (the fields), and each instance method takes an invisible pointer argument to the memory structure of that particular instance. Static classes, on the other hand, take up a sort of "global" memory, and static methods don't have the invisible "this" pointer argument to the instance data - there simply is no instance data, just a set of global slots for the static fields.

    However, that "global" data is alloted once per app domain. Unless you specifically create a singleton that is accessible across app domains (through something like MarshalByRefObject), your static class will be specific to a single app domain. If your DLL is loaded in a different app domain, its static data will be re-initialized, and will be independant of the first app domain.
    -Rob Teixeira
    Wednesday, December 17, 2008 5:03 PM
  • Hi Rob,

    Yes, my rhetoric "instance of the static class" was in error.   Static, by nature, has zero instances, agreed ... I was hoping for a link to some MSDN documentation with a sentence or two that indicates the AppDomain boundary for static vars/methods/classes, does such a thing exist?  Clearly you are of the mind that the boundary for static objects is the AppDomain. 

    Dan
    -DK
    Wednesday, December 17, 2008 5:24 PM
  • It actually has more to do with how the runtime handles assemblies than how it handles static classes. Assemblies can only be loaded into a single app-domain. If a process has two (or more) app domains defined, and an assembly gets loaded into the first app domain, the second app domain cannot see any details about the assembly that is loaded into app domain 1. It can't even access the classes or metadata defined in that assembly unless it also loads the assembly.

    And actually, you can create a quick test to prove this. Create a console app, and then add a class library to the solution. In the console app, create a reference to the class library. In the class library, create the following class:

    public class AppDomainController : MarshalByRefObject  
    {  
        private static Guid xxx = Guid.NewGuid();  
     
        public void WriteFile()  
        {  
            string path = @"C:\xxx_" + xxx.ToString("N") + ".txt";  
            File.WriteAllText(path, AppDomain.CurrentDomain.FriendlyName + " : " + xxx.ToString("N"));  
        }  

    Now, in the console app, create an instance of the appdomaincontroller class, and call writefile(). 

    AppDomainController a = new AppDomainController();
    a.WriteFile();

    This will create an instance and write a file to the C:\ folder. The name of the file will be based on the static GUID member. The contents of the file will give you the app domain name.

    Then, right below that code, create a new app domain, load the class library into it, and call the same method:

    AppDomain domain = AppDomain.CreateDomain("Domain2");
    AppDomainController b = (AppDomainController)domain.CreateInstanceFromAndUnwrap("ClassLibrary1.dll", "ClassLibrary1.AppDomainController");
    b.WriteFile();

    As you can see, when you run the console app, you end up with two files because the static GUID was initialized twice with different values, once for each app domain.
    -Rob Teixeira
    • Marked as answer by dotBomb Thursday, December 18, 2008 7:53 PM
    Thursday, December 18, 2008 5:31 PM
  • That's a great test, thanks Rob!

    Dan
    -DK
    Thursday, December 18, 2008 7:52 PM