Click to See Complete Forum and Search --> : Dynamic Types


zvenny
November 19th, 2007, 04:02 AM
I'm experimenting with external (xml) type or class definitions. With the various Builder classes available in .Net I'm able to generate my types @ runtime, based on the info in an xml ...AssemblyBuilder ab;
ModuleBuilder mb;
TypeBuilder tb;
Dictionary<string,Type> dicTypes=new Dictionary<string,Type>();

public Form1()
{
InitializeComponent();
ab = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("MyRandomAssembly"), AssemblyBuilderAccess.Run);
mb = ab.DefineDynamicModule("MyRandomModule");
}

private void button_LoadXmlTypeDefs(object sender, EventArgs e)
{
dicTypes.Clear();
foreach (DefinedType dType in m_Xml.Types)
{
tb = mb.DefineType(dType.sName, TypeAttributes.Public);
foreach (DefinedField dField in dType.Fields)
{
Type tp;

switch (dField.sType)
{
case "U8" : tp=typeof(byte); break;
case "U16": tp=typeof(UInt16); break;
case "S16": tp=typeof(Int16); break;
default : break;
}
tb.DefineField(dField.sName, tp, FieldAttributes.Public);
}

dicTypes.Add(dType.sName, tb.CreateType());
}
}I've tested this with xml files containing 100s of definitions and with consecutive passes of button_LoadXmlTypeDefs memory usage keeps increasing as show by Task Manager. dicTypes.Clear doesn't seem to clean up the types of the previously 'loaded' Xml file !

So, any idea idea how to get rid of my runtime generated types ?

boudino
November 19th, 2007, 09:55 AM
It is as CLR behaves. Once a type is loaded into app domain, it cannot be unloaded. Clearing the collection doesn't help. Try to call AppDomain.Unload() and pass your working domain to it. Don't forget to create new domain for next iteration in this case.

zvenny
November 20th, 2007, 03:03 AM
So if I understand this correct , I should create an AppDomain that 'hosts' the dynamic types at each iteration ? And of course Unload it when no longer required ?

All new to me, but thx for the hint !

boudino
November 20th, 2007, 04:06 AM
I understood it this way too.

erikvanhecke
November 20th, 2007, 04:16 AM
This is my stripped version, where I try to solve the problem. There is indeed no possibility to unload the type, module or assembly. In the reactions above I read about the ability to create an applicationdomain and unload this. But how do you relate this dynamic type to this namespace?




public Form1()
{
InitializeComponent();
ab = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
mb = ab.DefineDynamicModule("Module");
}

AssemblyName an = new AssemblyName("test");
AssemblyBuilder ab;
ModuleBuilder mb;


public void CreateObject()
{
TypeBuilder tb = mb.DefineType("class" + mb.GetTypes().Length.ToString(), TypeAttributes.Public);
//AppDomain appDom = AppDomain.CreateDomain("DynamicAppDomain");

for (int i = 0; i < 10; i++)
tb.DefineField("field" + i.ToString(), typeof(int), FieldAttributes.Public);

Type type1 = tb.CreateType();
object DObj = Activator.CreateInstance(type1);


//appDom.Load(an);
//AppDomain.Unload(appDom);
}

erikvanhecke
November 20th, 2007, 04:59 AM
Ok, I think I've found something that is close to the solution. There is only a bug with serialization at DefineDynamicAssembly:

Type 'System.Reflection.Emit.AssemblyBuilder' in assembly 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.

public void CreateObject()
{
AppDomain appDom = AppDomain.CreateDomain("MyDynamicAppDomain");
AssemblyBuilder ab = appDom.DefineDynamicAssembly(new AssemblyName("MyDynamicAssembly"),
AssemblyBuilderAccess.Run);
ModuleBuilder mb = ab.DefineDynamicModule("MydynamicModule");

TypeBuilder tb = mb.DefineType("MydynamicClass", TypeAttributes.Public);

for (int i = 0; i < 10; i++)
tb.DefineField("field" + i.ToString(), typeof(int), FieldAttributes.Public);

Type type1 = tb.CreateType();
object DObj = Activator.CreateInstance(type1);

AppDomain.Unload(appDom);
}