Using system;
Using system. reflection;
Using system. reflection. emit;
/// <Summary>
/// Create a dynamic type and add definitions for each public attribute
/// </Summary>
Public class dynamictypebuilder
{
Typebuilder TB;
/// <Summary>
/// Constructor
/// </Summary>
/// <Param name = "typenm"> name of the dynamic type </param>
Public dynamictypebuilder (string typenm)
{
// In Silverlight, assemblybuilderaccess does not have runandsave
Assemblybuilder AB = appdomain. currentdomain. definedynamicassembly (
New assemblyname ("tempassembly"), assemblybuilderaccess. Run );
Modulebuilder MB = AB. definedynamicmodule ("tempmodule ");
This. TB = Mb. definetype (typenm, typeattributes. Public );
}
/// <Summary>
/// Add a public read/write attribute and create a private field named propertynm + "field"
/// </Summary>
/// <Param name = "propertynm"> </param>
/// <Param name = "type"> </param>
Public void appendpublicproperty (string propertynm, type)
{
This. appendpublicproperty (propertynm, type, true, true );
}
/// <Summary>
/// Add a public attribute and create a private field named propertynm + "field ".
/// </Summary>
/// <Param name = "propertynm"> </param>
/// <Param name = "type"> </param>
/// <Param name = "canget"> whether to implement getter </param>
/// <Param name = "canset"> whether to implement setter </param>
Public void appendpublicproperty (string propertynm, type, bool canget, bool canset)
{
Fieldbuilder field = This. TB. definefield (string. Format ("{0} field", propertynm), type, fieldattributes. Private );
Propertybuilder property = Tb. defineproperty (propertynm, propertyattributes. hasdefault, type, null );
Methodattributes getsetattr = methodattributes. Public | methodattributes. specialname | methodattributes. hidebysig;
If (canget)
{
Methodbuilder getaccessor = Tb. definemethod (string. Format ("Get _ {0}", propertynm), getsetattr, type, type. emptytypes );
Ilgenerator getil = getaccessor. getilgenerator ();
# Region write the Il code
// Follow the instructions in the Il code and cannot run
//. Method public hidebysig specialname instance int32
// Get_a () cel managed
//{
/// Code size 12 (0xc)
//. Maxstack 1
//. Locals Init ([0] int32 CS $1 $0000)
// Il_0000: NOP
// Il_0001: ldarg.0
// Il_0002: ld1_int32 wpfapplication2.person: afield
// Il_0007: stloc.0
// Il_0008: Br. s il_000a
// Il_000a: ldloc.0
// Il_000b: Ret
//} // End of method person: get_a
// Follow the above il code and cannot run:
// Label getbrslabel = getil. definelabel ();
// Getil. emit (Opcodes. Nop );
// Getil. emit (Opcodes. ldarg_0 );
// Getil. emit (Opcodes. lddes, field );
// Getil. emit (Opcodes. stloc_0 );
// Getil. emit (Opcodes. br_s, getbrslabel );
// Getil. marklabel (getbrslabel );
// Getil. emit (Opcodes. ldloc_0 );
// Getil. emit (Opcodes. Ret );
# Endregion
// For an instance property, argument default is the instance. Load
// Instance, then load the private field and return, leaving
// Field value on the stack.
Getil. emit (Opcodes. ldarg_0 );
Getil. emit (Opcodes. lddes, field );
Getil. emit (Opcodes. Ret );
Property. setgetmethod (getaccessor );
}
If (canset)
{
Methodbuilder setaccessor = Tb. definemethod (string. Format ("SET _ {0}", propertynm), getsetattr, null, new type [] {type });
Setaccessor. defineparameter (1, parameterattributes. None, "value ");
Ilgenerator setil = setaccessor. getilgenerator ();
// Load the instance and then the numeric argument, then store
// Argument in the field.
Setil. emit (Opcodes. ldarg_0 );
Setil. emit (Opcodes. ldarg_1 );
Setil. emit (Opcodes. stdes, field );
Setil. emit (Opcodes. Ret );
Property. setsetmethod (setaccessor );
}
}
/// <Summary>
/// Call this method after each public attribute is added to define and load the dynamic type,
/// Later, the dynamic type can be instantiated through activator. createinstance ().
/// </Summary>
/// <Returns> </returns>
Public type createdynamictype ()
{
Return this. TB. createtype ();
}
}