all groups > dotnet clr > september 2005 >
You're in the

dotnet clr

group:

deserializing types defined in dynamic assemblies


deserializing types defined in dynamic assemblies rein.petersen NO[at]SPAM gmail.com
9/27/2005 5:50:20 PM
dotnet clr:
Hi All,

I posted this to an xml group but I thought this post might fare better
here....

I've been working on a means to create dynamic asemblies (modules
actually) from parsing XSD schemas which creates a perfect .net
representation of the schema at hand (dynamically).

My next hurdle is to deserialize xml documents (that conform to the
schemas from which dynamic modules were derived) to the types from the
dynamic module.

Before I go posting code like crazy, here is the main problem I'm
facing:

When I try to deserialize, an exception is raised: "The invoked member
is not supported in a dynamic module."

Which member the serializer is invoking is unknown to me. This may be a
serious problem if I can't find a way to (de)serialize into dynamic
types. An acceptable work-around is the save the dynamic assembly to
disk - would the innaccessible members become available for invocation?

Thanks in advance, Rein
Re: deserializing types defined in dynamic assemblies rein.petersen NO[at]SPAM gmail.com
9/28/2005 6:53:21 AM
I gave up on the transient assembly solution and opted to write the
assembly to disk, then read it back again in hopes that I can use the
XmlSerializer to deserialize xml documents into objects dynamically
defined. I created a test windows form which I think should work but I
receive an error of the same nature when I try to deserialize...

Here is the code for the form:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Reflection;
using System.Reflection.Emit;

namespace DynamicTypeDeserializer
{
public class DTD : System.Windows.Forms.Form
{
private System.Windows.Forms.Button btnDDT;

private System.ComponentModel.Container components = null;

public static byte[] GetAssemblyBytes(string filename)
{
System.IO.FileStream fs = new System.IO.FileStream(filename,
System.IO.FileMode.Open);
byte[] buffer = new byte[(int) fs.Length];
fs.Read(buffer, 0, buffer.Length);
fs.Close();

return buffer;
}


public static Assembly AssemblyResolver(object sender,
ResolveEventArgs args)
{
AppDomain domain = (AppDomain) sender;
EmitAssembly(domain);
byte[] rawAssembly = GetAssemblyBytes("DynMod.dll");
byte[] rawSymbolStore = GetAssemblyBytes("DynMod.pdb");
Assembly assembly = domain.Load(rawAssembly, rawSymbolStore);
return assembly;
}


public static void EmitAssembly(AppDomain domain)
{
AssemblyName aName = new AssemblyName();
aName.Name = "DynamicModulesAssembly";

AssemblyBuilder ab = domain.DefineDynamicAssembly(aName,
AssemblyBuilderAccess.Save);
ModuleBuilder mb = ab.DefineDynamicModule("DynMod", "DynMod.dll",
true);

System.Reflection.Emit.TypeBuilder tb =
mb.DefineType("Person",System.Reflection.TypeAttributes.Class|System.Reflection.TypeAttributes.Public);

System.Reflection.Emit.FieldBuilder fb =
tb.DefineField("Name",typeof(string),System.Reflection.FieldAttributes.Public);

System.Reflection.Emit.ConstructorBuilder cb =
tb.DefineDefaultConstructor(System.Reflection.MethodAttributes.Public);

tb.CreateType();

ab.Save("DynMod.dll");
}



public object DeserializeDynamicType()
{
AppDomain appdom = AppDomain.CurrentDomain; //AppDomain appdom =
System.Threading.Thread.GetDomain();

appdom.AssemblyResolve+=new ResolveEventHandler(AssemblyResolver);

object person=null;
System.Type personType;

try
{
// You must supply a valid fully qualified assembly name here.
System.Runtime.Remoting.ObjectHandle handle =
appdom.CreateInstance("DynamicModulesAssembly", "Person");

person = handle.Unwrap();
personType = person.GetType();
if (personType != null)
{
using (System.IO.FileStream fs = new
System.IO.FileStream(@"c:\person.xml",System.IO.FileMode.Open))
{
try
{
System.Xml.Serialization.XmlSerializer xs = new
System.Xml.Serialization.XmlSerializer(personType);
person = xs.Deserialize(fs);
}
catch (System.Exception ex)
{
System.Console.WriteLine(ex.Message);

/* ??? "Unable to generate a serializer for type Person from
assembly <Unknown>
* because the assembly may be dynamic. Save the assembly
and load it from
* disk to use it with XmlSerialization."
*
* >>> That is what I thought I was doing here ?!? I'm
confused.
*/
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}

return person;
}


public DTD()
{
InitializeComponent();
}

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code

private void InitializeComponent()
{
this.btnDDT = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// btnDDT
//
this.btnDDT.Location = new System.Drawing.Point(56, 64);
this.btnDDT.Name = "btnDDT";
this.btnDDT.Size = new System.Drawing.Size(176, 23);
this.btnDDT.TabIndex = 0;
this.btnDDT.Text = "Deserialize Dynamic Type";
this.btnDDT.Click += new System.EventHandler(this.btnDDT_Click);
//
// DTD
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.btnDDT);
this.Name = "DTD";
this.Text = "Dynamic Type Deserializer";
this.ResumeLayout(false);

}
#endregion

[STAThread]
static void Main()
{
Application.Run(new DTD());
}

private void btnDDT_Click(object sender, System.EventArgs e)
{
object person = this.DeserializeDynamicType();
string name = (string)
person.GetType().InvokeMember("Name",System.Reflection.BindingFlags.Public,null,person,null);
MessageBox.Show(name);
}
}
}
AddThis Social Bookmark Button