5

Ok, I have googled this for almost two days and I have tried almost all SO solutions that are related to this error, but nothing works. And most questions about this are for Security ssettings on Click-once applications, JSON, web applications etc. But nothing for a plain old winforms app.

Here is the full error

System.TypeAccessException: Attempt by method 'Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterSystemSetup.Write3_SystemSetup(System.Object)' to access type 'DataFacture.Common.Globals+SystemSetup' failed. at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterSystemSetup.Write3_SystemSetup(Object o)

Here is a simplified version of the'SystemSetup' class

public class SystemSetup
    {
        private string machineId, windowsVersion;

        public SystemSetup() { }
        public SystemSetup(string machineId, string windowsVersion)
        {
            this.machineId = machineId;
            this.windowsVersion = windowsVersion
        }

        public string MachineID { get { return machineId; } set { machineId = value; } }
        public string WindowsVersion{ get { return windowsVersion; } set { windowsVersion= value; } }
    }

Now I'm trying to generate an XML of a SystemSetup object using the following code, and at the 'writer.Serialize(wfile, objectSerializer);' line, the error occurs

public static void WriteXML(Object objectSerializer, String XMLPath, String FileName)
    {
        try
        {
            if (XMLPath.Substring(XMLPath.Length - 1, 1) != @"/")
                XMLPath = String.Format("{0}\\", XMLPath);

            XmlSerializer writer = null;
            Type objectType = objectSerializer.GetType();
            switch (objectType.Name)
            {
                case "SystemSetup":
                    writer = new XmlSerializer(typeof(Globals.SystemSetup));
                    break;
            }

            var wfile = new System.IO.StreamWriter(String.Format("{0}{1}", XMLPath, FileName));
            writer.Serialize(wfile, objectSerializer);
            wfile.Close();
        }
        catch (Exception ex)
        {
            ErrorHandler.ShowErrorMessage(ex);
        }
    }

This is a winforms applications. It is not click once. And I have not enforced any security restrictions on any assembly. Also, there are no 3rd party assemblies that I'm calling from here.

Edit: The above are in the same namespace but in separate class files. If I put them into one class file, it works. Not sure if that helps

TheDanMan
  • 1,746
  • 1
  • 17
  • 22

1 Answers1

9

After tons of fiddling around. I found the problem; rookie mistake on my side. My "Globals" class where the "SystemSetup" object was being invoked wasn't specified to be private or public. I was just

static class Globals
{
    public class SystemSetup
    {
        //My code here
    }
}

and at design time, there poses no issues. You can access all the classes inside "Globals". However, at runtime, the debugger has trouble accessing the "Globals" class and therefore you need to specify it to be "public"

public static class Globals
{
    public class SystemSetup
    {
        //My code here
    }
}

I totally overlooked this. I took it for granted that since I could access the class at design time and the compiler had no issues building the solution, then it should work at runtime and since the "SystemSetup" class was public, I assumed it would work. OOP Programming 101, totally missed it.

TheDanMan
  • 1,746
  • 1
  • 17
  • 22
  • Should say that without any modified set, the class will default to the lowest, so with no modifier I believe the static class would default to `private` – Luke T O'Brien Mar 16 '18 at 09:38
  • 3
    The default access modifier for classes is `internal`, not `private`. See [docs](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/access-modifiers#class-and-struct-accessibility). – vit Apr 10 '19 at 12:38
  • @vit Well, we have two classes inside each other, but since the class we are talking about is the outermost class, you are right. The default access level for any direct _member of a namespace_ (such as the outermost class or struct) is `internal`. The default access level for any _member of a class_ or struct (including a nested class or struct) is `private`. So if you removed the innermost `public` in the example from this answer, the default would be `private` for the nested class `SystemSetup`. – Jeppe Stig Nielsen Sep 08 '22 at 15:57