Skip to content

Instantly share code, notes, and snippets.

@bh3605
Last active August 29, 2015 14:27
Show Gist options
  • Save bh3605/a3a830cc1bdc20368978 to your computer and use it in GitHub Desktop.
Save bh3605/a3a830cc1bdc20368978 to your computer and use it in GitHub Desktop.
Builds an object type from a struct containing all of the variable members of the struct as properties with getters and setters
imports System.Reflection
imports System.Reflection.Emit
imports System.Threading
''' <summary>
''' The purpose of this class is to take a struct and build and return an object type containing all of
''' the variable members of the struct as properties with getters and setters. You can then make an
''' instance of the object type by calling activator.createinstance(type).
''' Usage: dim converter = new StructConverter()
''' dim structObjectType as Type = converter.buildDynamicProperties(GetType(YourStruct))
''' bindingList = Ctype(Activator.CreateInstance(GetType(BindingList(Of )).MakeGenericType(New Type() {structObjectType})), IBindingList)
''' Or:
''' dim struct = GetType(YourStruct)
''' dim newTestData = activator.createinstance(structObjectType)
''' for each field as reflection.fieldinfo in struct.GetFields
''' testDataType.invokemember(field.name, reflection.bindingflags.setproperty, _
''' nothing, newTestData, new object() {field.getvalue(testing)}) 'testing = 1st index of array of type YourStruct
''' testDataType.invokemember(field.name, reflection.bindingflags.getproperty, _
''' nothing, newTestData, new object() {})
''' Next
''' </summary>
public class StructConverter
''Reflection example for structs
'
'dim struct = GetType(typTestData)
'for each field as Reflection.fieldinfo in struct.GetFields
' Dim Value As Object = field.GetValue(testing)
' console.writeline(field.Name & "=" & Value.ToString)
'Next
'
'Example for assigning values from a struct to a type
'
' for each field as reflection.fieldinfo in struct.GetFields
'dim fieldValue = field.getvalue(testing)
' testDataType.invokemember(field.name, reflection.bindingflags.setproperty, _
' nothing, newTestData, new object() {field.getvalue(testing)})
' testDataType.invokemember(field.name, reflection.bindingflags.getproperty, _
' nothing, newTestData, new object() {})
'Next
public sub new()
End sub
friend function buildDynamicProperties(data as Type)
dim name = data.name
dim myDomain as AppDomain = Thread.GetDomain()
dim myAsmName as New AssemblyName()
'myAsmName.Name = "DynamicRuntimePropertiesAssembly"
myAsmName.Name = name
' To generate a persistable assembly, specify AssemblyBuilderAccess.RunAndSave.
dim myAsmBuilder as AssemblyBuilder = myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.RunAndSave)
' Generate a persistable, single-module assembly.
dim myModBuilder as ModuleBuilder = _
myAsmBuilder.DefineDynamicModule(myAsmName.Name, myAsmName.Name & ".dll")
dim myTypeBuilder as TypeBuilder = myModBuilder.DefineType("Struct"&name &"Properties", TypeAttributes.Public)
for each prop as fieldinfo in data.getfields()
' Define a private field to hold the property value.
dim customerNameBldr as FieldBuilder = myTypeBuilder.DefineField(prop.name, _
prop.FieldType, FieldAttributes.Private)
' The last argument of DefineProperty is Nothing, because the
' property has no parameters. (If you don't specify Nothing, you must
' specify an array of Type objects. For a parameterless property,
' use an array with no elements: New Type() {})
Dim custNamePropBldr As PropertyBuilder =
myTypeBuilder.DefineProperty(prop.name, PropertyAttributes.HasDefault, _
prop.fieldtype, Nothing)
' The property set and property get methods require a special set of attributes.
dim getSetAttr as MethodAttributes = MethodAttributes.public Or MethodAttributes.SpecialName Or MethodAttributes.HideBySig
' Define the "get" accessor method for the property.
dim custNameGetPropMthdBldr as MethodBuilder =
myTypeBuilder.DefineMethod("Get"&prop.name, getSetAttr, prop.fieldtype, Type.EmptyTypes)
dim custNameGetIL as ILGenerator = custNameGetPropMthdBldr.GetILGenerator()
custNameGetIL.Emit(OpCodes.Ldarg_0)
custNameGetIL.Emit(OpCodes.Ldfld, customerNameBldr)
custNameGetIL.Emit(OpCodes.Ret)
' Define the "set" accessor method for CustomerName.
dim custNameSetPropMthdBldr as MethodBuilder =
myTypeBuilder.DefineMethod("get_"&prop.name, getSetAttr, Nothing, New Type() {prop.fieldtype})
dim custNameSetIL as ILGenerator = custNameSetPropMthdBldr.GetILGenerator()
custNameSetIL.Emit(OpCodes.Ldarg_0)
custNameSetIL.Emit(OpCodes.Ldarg_1)
custNameSetIL.Emit(OpCodes.Stfld, customerNameBldr)
custNameSetIL.Emit(OpCodes.Ret)
' Last, we must map the two methods created above to our PropertyBuilder to
' their corresponding behaviors, "get" and "set" respectively.
custNamePropBldr.SetGetMethod(custNameGetPropMthdBldr)
custNamePropBldr.SetSetMethod(custNameSetPropMthdBldr)
next
dim retval as Type = myTypeBuilder.CreateType()
' Save the assembly so it can be examined with Ildasm.exe,
' or referenced by a test program.
'myasmBuilder.Save(myasmName.Name & ".dll")
return retval
end function
end class
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment