Strange error compiling a class at runtime

Hi all

I am trying to compile a class at runtime and I get this strange error ("System.RuntimeType is inaccessible due to its protection level. Only public types can be processed.")
when I try to serialise my xml input into the newly compiled assembly.

I have attached a rather large code snippet that I use to test my compiler and I keep getting the error

Every method in the customer.cs class is public so Im not sure why Im get this error.

Basically I get a class object from a file stored somewhere on the server

Input is provided via XML from the UI, for this example I simply save the xml to file and loaded it into a Xml document that is then serialized into customer.cs.

Help would most definitely be appreciated
//
//TEST CLASS
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.CodeDom.Compiler;
using System.IO;
 
namespace MarksCompilerTest
{
    public class Tester
    { 
        public static void Main()
        {
            //declare the name of the new class to create
            string nameSpace = "Customer";
            //get the class object from file
            string Classcs = System.IO.File.ReadAllText(@"C:\Customer.cs");
            //compile the class 
            object Class = Compiler.CompileClass(Classcs, nameSpace);
 
            //get input xml
            XmlDocument doc = new XmlDocument();
            doc.Load(@"C:\customer_1.xml");
            
            //merge input xml into newly compiled class, BANG!! ERROR :'(
            object mergedClass = XML.SaveXMLtoClass(doc, Class);
        }
    }
 
    internal class Compiler
    {        
        static public object CompileClass(string classobj, string nameSpace)
        {
            CompilerResults results = CompileCode(classobj, nameSpace);
            if (results.Errors.Count != 0)
            {
                Exception ex = new Exception("Cannot compile class[" + nameSpace + "]", new Exception(XML.ConvertToXMLString(results.Errors)));
                ex.Source = "Compiler.CompileClass()";
                throw ex;
                return null;
            }
            else
            {
                Type[] type = results.CompiledAssembly.GetTypes();
                return type[0];
            }
        }
 
        private static CompilerResults CompileCode(string source, string nameSpace)
        {
            var providerOptions = new Dictionary<string, string>();
            providerOptions.Add("CompilerVersion", "v3.5");
 
            var provider = new Microsoft.CSharp.CSharpCodeProvider(providerOptions);
 
            CompilerParameters parameters = new CompilerParameters();
 
            // Generate an a class library instead of a executeable
            parameters.GenerateExecutable = false;
 
            // Generate debug information.
            parameters.IncludeDebugInformation = true;
 
            parameters.OutputAssembly = nameSpace;
 
            // Add an assembly reference.
            MarksCompilerTest.Properties.Settings settings = new MarksCompilerTest.Properties.Settings();
            foreach (string assembly in settings.Assemblies)
            {
                parameters.ReferencedAssemblies.Add(assembly);
            }
 
            //Add using statements to source code
            var sourceBuilder = new StringBuilder();
            foreach (string usingStatement in settings.Usings)
            {
                sourceBuilder.AppendLine("using " + usingStatement + ";");
            }
            sourceBuilder.AppendLine(source);
            source = sourceBuilder.ToString();
 
            // Save the assembly as to memory.
            parameters.GenerateInMemory = true;
 
            parameters.OutputAssembly = nameSpace;
 
            // Set the level at which the compiler 
            // should start displaying warnings.
            parameters.WarningLevel = 3;
 
            // Set whether to treat all warnings as errors.
            parameters.TreatWarningsAsErrors = false;
 
            // Set compiler argument to optimize output.
            parameters.CompilerOptions = "/optimize";
 
            
            // Invoke compilation.
            return provider.CompileAssemblyFromSource(parameters, source);
 
        }
    }
 
        internal class XML
        {
            public static string ConvertToXMLString(object obj)
            {
                var memoryStream = new MemoryStream();
                var doc = new XmlDocument();
 
                try
                {
                    XmlSerializer serializer = new XmlSerializer(obj.GetType());
                    XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
                    serializer.Serialize(xmlTextWriter, obj);
                    memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
                    return UTF8ByteArrayToString(memoryStream.ToArray());
                }
                catch (Exception e)
                {
                    return "";
                }
                finally
                {
                    memoryStream.Flush();
                    memoryStream.Close();
                    memoryStream.Dispose();
                }
            }
 
            static private string UTF8ByteArrayToString(Byte[] characters)
            {
 
                UTF8Encoding encoding = new UTF8Encoding();
                String constructedString = encoding.GetString(characters);
                return (constructedString);
            }
 
            public static object SaveXMLtoClass(XmlDocument doc, object Class)
            {
                StringReader stream = null;
                XmlTextReader reader = null;
                try
                {
                    var serializer = new XmlSerializer(Class.GetType());                    
                    stream = new StringReader(doc.InnerXml);
                    reader = new XmlTextReader(stream);
                    return (object)serializer.Deserialize(reader);
                }
                catch (Exception ex)
                {
                    throw;
                    return null;
                }
                finally
                {
                    if (stream != null) stream.Close();
                    if (reader != null) reader.Close();
                }
            }
        }
}
 
 
//
// App config
//
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="MarksCompilerTest.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
        </sectionGroup>
    </configSections>
    <applicationSettings>
        <MarksCompilerTest.Properties.Settings>
            <setting name="Usings" serializeAs="Xml">
                <value>
                    <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
                        <string>System</string>
                        <string>System.Text</string>
                        <string>System.Xml</string>
                    </ArrayOfString>
                </value>
            </setting>
            <setting name="Assemblies" serializeAs="Xml">
                <value>
                    <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
                        <string>System.dll</string>
                        <string>System.XML.dll</string>
                    </ArrayOfString>
                </value>
            </setting>
        </MarksCompilerTest.Properties.Settings>
    </applicationSettings>
</configuration>
 
 
 
//
// Customer_1.xml  (INPUT) 
//
<?xml version="1.0" encoding="UTF-8" ?>
<Customer>  
  <FirstName>Mark</FirstName>
  <LastName>Myburgh</LastName>
  <IDNumber>99999999999</IDNumber>
  <DateOfBirth>2000-07-29T02:50:43.2324</DateOfBirth>
  <Email>m@m.co.za</Email>
  <Address>
    <Line1>CODE HELL</Line1>
    <Line2>Crash Street</Line2>
    <Line3></Line3>
    <City>Broken</City>
    <Code>666</Code>
  </Address>
</Customer>
 
 
//
//  Customer.cs (FILE TO BE COMPILED)
//
public class Customer
{
 
  public string FirstName { get; set; }
  public string LastName { get; set; }  
  public string IDNumber { get; set; } 
  public DateTime DateOfBirth { get; set; } 
  public string Email { get; set; }      
  public Address Address { get; set; }
}
 
public class Address
{
    public string Line1 { get; set; }
    public string Line2 { get; set; }
    public string Line3 { get; set; }
    public string City { get; set; }
    public int Code { get; set; }
    public Address() { }
}

Open in new window

LVL 1
MarkMyburghAsked:
Who is Participating?
 
MarkMyburghConnect With a Mentor Author Commented:
THIS has to be one of the most painful ball aches I have ever experienced trying to solve this error;
With some help from one of our senior member we found the issue;
have a look at the updated code;
thanks to all... :D
 
Mark

//// UPDATED CODE IN TESTER APP
 public class Tester
    {
        public static void Main()
        {
            //declare the name of the new class to create
            string nameSpace = "Customer";
 
            //get the class object from file
            string source = System.IO.File.ReadAllText(@"C:\Customer.cs");
 
            //compile the class 
            Type type = Compiler.CompileClass(source, nameSpace);
 
            //get input xml
            XmlDocument doc = new XmlDocument();
            doc.Load(@"C:\Customer_1.xml");
 
           object mergedClass = SeriaizationHelper.XmlDeserialize(doc, type);
 
            Console.WriteLine(type.GetProperty("IdNumber").GetValue(mergedClass,null).ToString());
 
            Console.Read();
        }
    }
 
    internal class SeriaizationHelper
    {
        public static object XmlDeserialize(XmlDocument doc, Type t)
        {
            MemoryStream stream = new MemoryStream();
 
            doc.Save(stream);
 
            stream.Position = 0;
 
            return new XmlSerializer(t).Deserialize(stream);
        }
        public static XmlDocument XmlSerialize(Customer customer, Type t)
        {
            XmlDocument doc = new XmlDocument();
            MemoryStream stream = new MemoryStream();
 
            new XmlSerializer(t).Serialize(stream, customer);
 
            stream.Position = 0;
 
            doc.Load(stream);
 
            return doc;
        }
    
    }
 
 
// UPDATED CUSTOMER CLASS
using System;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
 
[Serializable()]
public class Customer
{
    private string _firstName;
    private string _lastName;
    private string _idNumber;
    private DateTime _dateOfBirth;
    private string _email;
    private Address _address;
 
    [XmlElement]
    public string FirstName
    {
        get { return _firstName; }
        set { _firstName = value; }
    }
 
    [XmlElement]
    public string LastName
    {
        get { return _lastName; }
        set { _lastName = value; }
    }
 
    [XmlElement]
    public string IdNumber
    {
        get { return _idNumber; }
        set { _idNumber = value; }
    }
 
    [XmlElement]
    public DateTime DateOfBirth
    {
        get { return _dateOfBirth; }
        set { _dateOfBirth = value; }
    }
 
    [XmlElement]
    public string Email
    {
        get { return _email; }
        set { _email = value; }
    }
 
    [XmlElement]
    public Address Address
    {
        get { return _address; }
        set { _address = value; }
    }
 
    public Customer () {
 
        Address = new Address();
    }
}
 
[Serializable()]
public class Address
{
    private string _line1;
    private string _line2;
    private string _line3;
    private string _city;
    private int _code;
 
    [XmlElement]
    public string Line1
    {
        get { return _line1; }
        set { _line1 = value; }
    }
    [XmlElement]
    public string Line2
    {
        get { return _line2; }
        set { _line2 = value; }
    }
 
    public string Line3
    {
        get { return _line3; }
        set { _line3 = value; }
    }
    [XmlElement]
    public string City
    {
        get { return _city; }
        set { _city = value; }
    }
    [XmlElement]
    public int Code
    {
        get { return _code; }
        set { _code = value; }
    }
 
    public Address() { }
}
 
 
//UPDATED XML CLASS
<?xml version="1.0"?>
<Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <FirstName>John</FirstName>
  <LastName>Doe</LastName>
  <IdNumber>551022 5435 099</IdNumber>
  <DateOfBirth>2008-10-17T15:52:18.890625+02:00</DateOfBirth>
  <Email>foo@com.com</Email>
  <Address>
    <Line1>Line 1</Line1>
    <Line2>Line 2</Line2>
    <Line3>Line 3</Line3>
    <City>Some Place</City>
    <Code>1102</Code>
  </Address>
</Customer>

Open in new window

0
 
Anurag ThakurConnect With a Mentor Technical ManagerCommented:
are you sure you Customer object is a class
it looks like you are defining an interface - i cannot see any variables which are being set or returned - this class just compiled gives errors

public class Customer
{
  public string FirstName { get; set; }
  public string LastName { get; set; }  
  public string IDNumber { get; set; }
  public DateTime DateOfBirth { get; set; }
  public string Email { get; set; }      
  public Address Address { get; set; }
}
0
 
MarkMyburghAuthor Commented:
Hi Rag
yip it is a class.  In 2008 you don't have to declare private variables for properties anymore :
            public string FirstName { get; set; }      <-- this is how you declare a property in 2008 :D  sweet hey.  I LIKE it a lot :D
Also I'm sure you noticed that there is no references in the class, at runtime I add all the Using referencies before compiling the source code.
            var sourceBuilder = new StringBuilder();
            foreach (string usingStatement in settings.Usings)
            {
                sourceBuilder.AppendLine("using " + usingStatement + ";");
            }
            sourceBuilder.AppendLine(source);
            source = sourceBuilder.ToString();

What i am worred about is that the CompilerResults.Error is not populated, how would one attach onto the compiler stream.  that way i can have a look at the output and see if there is any compile errors.
0
Cloud Class® Course: Microsoft Windows 7 Basic

This introductory course to Windows 7 environment will teach you about working with the Windows operating system. You will learn about basic functions including start menu; the desktop; managing files, folders, and libraries.

 
MarkMyburghAuthor Commented:
thought i found the error but no i still get the issue.
below find the update customer class

//
//  Customer.cs (FILE TO BE COMPILED)
//
public class Customer
{
 
  public string FirstName { get; set; }
  public string LastName { get; set; }  
  public string IDNumber { get; set; } 
  public DateTime DateOfBirth { get; set; } 
  public string Email { get; set; }      
  public Address Address { get; set; }
  publlic Customer (){}
}
 
public class Address
{
    public string Line1 { get; set; }
    public string Line2 { get; set; }
    public string Line3 { get; set; }
    public string City { get; set; }
    public int Code { get; set; }
    public Address() { }
}

Open in new window

0
 
Bob LearnedCommented:
Do it matter that you have a typo?

    publlic Customer (){}
0
 
MarkMyburghAuthor Commented:
lol yeah that just on here i simple copied and pasted the example from above.  my bad.  The code is clean;
 

public class Customer
{
  public string FirstName { get; set; }
  public string LastName { get; set; }  
  public string IDNumber { get; set; } 
  public DateTime DateOfBirth { get; set; } 
  public string Email { get; set; }      
  public Address Address { get; set; }
  public Customer () {}
}
 
public class Address
{
    public string Line1 { get; set; }
    public string Line2 { get; set; }
    public string Line3 { get; set; }
    public string City { get; set; }
    public int Code { get; set; }
    public Address() { }
}

Open in new window

0
 
Bob LearnedCommented:
Hmmm...it looks like you are using auto-implemented properties, which means that the fields are generated at run-time (I believe).  What happens if you use explicitly declared fields for the property (just a test)?
0
 
MarkMyburghAuthor Commented:
:'''(   and there goes that bubble ....
same error
 
but i found a few errors inside the compiled assembly, even though the compiler did not through an error compiling the code:
error 1:
DeclaringMethod = '((System.RuntimeType)(type)).DeclaringMethod' threw an exception of type 'System.InvalidOperationException'

base {System.SystemException} = {"Method may only be called on a Type for which Type.IsGenericParameter is true."}

error 2:
GenericParameterAttributes = '((System.RuntimeType)(type)).GenericParameterAttributes' threw an exception of type 'System.InvalidOperationException'

base {System.SystemException} = {"Method may only be called on a Type for which Type.IsGenericParameter is true."}

error 3:
GenericParameterPosition = '((System.RuntimeType)(type)).GenericParameterPosition' threw an exception of type 'System.InvalidOperationException'

base {System.SystemException} = {"Method may only be called on a Type for which Type.IsGenericParameter is true."}


public class Customer
{
    private string _fn;
    private string _ln;
    private string _ID;
    private DateTime _dob;
    private string _em;
    private Address _add;
 
    public string FirstName 
    {
        get { return _fn; }
        set { _fn = value; }
    }
 
    public string LastName
    {
        get { return _ln; }
        set { _ln = value; }
    }
 
    public string IDNumber
    {
        get { return _ID; }
        set { _ID = value; }
    }
 
    public DateTime DateOfBirth
    {
        get { return _dob; }
        set { _dob = value; }
    }
 
    public string Email
    {
        get { return _em; }
        set { _em = value; }
    }
 
    public Address Address
    {
        get { return _add; }
        set { _add = value; }
    }
 
    public Customer () {}
}
 
public class Address
{
    private string _l1;
    private string _l2;
    private string _l3;
    private string _ct;
    private int _cd;
 
    public string Line1
    {
        get { return _l1; }
        set { _l1 = value; }
    }
 
    public string Line2
    {
        get { return _l2; }
        set { _l2 = value; }
    }
 
    public string Line3
    {
        get { return _l3; }
        set { _l3 = value; }
    }
 
    public string City
    {
        get { return _ct; }
        set { _ct = value; }
    }
 
    public int Code
    {
        get { return _cd; }
        set { _cd = value; }
    }
 
    public Address() { }
}

Open in new window

0
 
Bob LearnedCommented:
I believe that I have too narrow of a view to understand your problem (from where I am sitting).
0
 
MarkMyburghAuthor Commented:
hmmm
you could try compile the code on yourside and see what you get.
open a new project
copy and past the class into a new class file
add a config file to the app and copy the config settings from above
create a new file at c:\  call it customer.cs and past the customer class info from above

that should take care of all that needs to be created.
0
 
Bob LearnedCommented:
That code compiles just fine, but I am using 2005, and not 2008 (which I don't have at work).
0
 
MarkMyburghAuthor Commented:
do you still get the same error?
I'm just loading up 2005 to determine if i get the same error.
Question tho after compiling the object did the xml seriliasation step work?
 //get input xml
            XmlDocument doc = new XmlDocument();
            doc.Load(@"C:\customer_1.xml");
           
            //merge input xml into newly compiled class, BANG!! ERROR :'(
            object mergedClass = XML.SaveXMLtoClass(doc, Class);

this is the section thats giving me so much grief
0
 
MarkMyburghAuthor Commented:
nope same error on 2005 as well.  cannot serialise the xml into the newly compiled class
0
 
Bob LearnedCommented:
What is this code testing?  Are you trying to compare the compiled class against the serialized XML file?
0
 
MarkMyburghAuthor Commented:
2 things;
1 :
  compile a class object
2:
    serialize a xml file into the new compiled class object
 
0
 
Bob LearnedConnect With a Mentor Commented:
Since your class instance is declared as 'object', there would not be any way that I know of to get the serializer to work.
0
 
MarkMyburghAuthor Commented:
strange thing is;  if i add the class to the projec
and do the following:
{
            //declare the name of the new class to create
            string nameSpace = "Customer";
            //get the class object from file
            //string Classcs = System.IO.File.ReadAllText(@"C:\Customer.cs");
            //compile the class
            //object Class = Compiler.CompileClass(Classcs, nameSpace);
           customer Class = new Customer();

            //get input xml
            XmlDocument doc = new XmlDocument();
            doc.Load(@"C:\customer_1.xml");
           
            //merge input xml into newly compiled class, BANG!! ERROR :'(
            object mergedClass = XML.SaveXMLtoClass(doc, Class);
        }
 
I can serialiase the object no error.  Only when i use the compiled version of the same class do i get the error :(
0
 
MarkMyburghAuthor Commented:
this is the method i'm using to serialize
 public static object SaveXMLtoClass(XmlDocument doc, object Class)
            {
                StringReader stream = null;
                XmlTextReader reader = null;
                try
                {
                    var serializer = new XmlSerializer(Class.GetType());                    
                    stream = new StringReader(doc.InnerXml);
                    reader = new XmlTextReader(stream);
                    return (object)serializer.Deserialize(reader);
                }
                catch (Exception ex)
                {
                    throw;
                    return null;
                }
                finally
                {
                    if (stream != null) stream.Close();
                    if (reader != null) reader.Close();
                }
            }
0
 
MarkMyburghAuthor Commented:
found this might help you out
http://forums.asp.net/t/1323181.aspx 
0
 
MarkMyburghAuthor Commented:
ignore my previous post:  I pasted it into the wrong window
0
 
MarkMyburghAuthor Commented:
Managed to resolve the error.  Thanks all for your assistance.
save coding
0
 
MarkMyburghAuthor Commented:
Managed to resolve error.  Thanks all for your assistance and input
save coding
0
 
ShahnaseemCommented:
I have seen your comments to solve the problem, but if you could specifically tell us what you have done to solve the problem it will be great.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.