Создавать класс динамически во время выполнения
У меня есть такой метод: (это общий метод, и DYNAMIC_CLASS_TYPE
изменится в ситуации на другую ситуацию)
Dim res = f.MyMethod(Of DYNAMIC_CLASS_TYPE)("select Id, Name from myTable")
Я хочу создать динамический класс, основанный на столбцах моего запроса, а затем передать класс вместо DYNAMIC_CLASS_TYPE
,
Как я могу это сделать?
4 ответа
Решение
Мне наконец удалось это сделать. Мой код как:
Public Shared Function CreateClass(ByVal className As String, ByVal properties As Dictionary(Of String, Type)) As Type
Dim myDomain As AppDomain = AppDomain.CurrentDomain
Dim myAsmName As New AssemblyName("MyAssembly")
Dim myAssembly As AssemblyBuilder = myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.Run)
Dim myModule As ModuleBuilder = myAssembly.DefineDynamicModule("MyModule")
Dim myType As TypeBuilder = myModule.DefineType(className, TypeAttributes.Public)
myType.DefineDefaultConstructor(MethodAttributes.Public)
For Each o In properties
Dim prop As PropertyBuilder = myType.DefineProperty(o.Key, PropertyAttributes.HasDefault, o.Value, Nothing)
Dim field As FieldBuilder = myType.DefineField("_" + o.Key, GetType(Integer), FieldAttributes.[Private])
Dim getter As MethodBuilder = myType.DefineMethod("get_" + o.Key, MethodAttributes.[Public] Or MethodAttributes.SpecialName Or MethodAttributes.HideBySig, o.Value, Type.EmptyTypes)
Dim getterIL As ILGenerator = getter.GetILGenerator()
getterIL.Emit(OpCodes.Ldarg_0)
getterIL.Emit(OpCodes.Ldfld, field)
getterIL.Emit(OpCodes.Ret)
Dim setter As MethodBuilder = myType.DefineMethod("set_" + o.Key, MethodAttributes.[Public] Or MethodAttributes.SpecialName Or MethodAttributes.HideBySig, Nothing, New Type() {o.Value})
Dim setterIL As ILGenerator = setter.GetILGenerator()
setterIL.Emit(OpCodes.Ldarg_0)
setterIL.Emit(OpCodes.Ldarg_1)
setterIL.Emit(OpCodes.Stfld, field)
setterIL.Emit(OpCodes.Ret)
prop.SetGetMethod(getter)
prop.SetSetMethod(setter)
Next
Return myType.CreateType()
End Function
Возвращаемое значение функции - Тип моего Пользовательского Класса.
Кажется, есть ошибка. Я думаю, что эта строка:
Dim field As FieldBuilder = myType.DefineField("_" + o.Key, GetType(Integer), FieldAttributes.[Private])
должен выглядеть так:
Dim field As FieldBuilder = myType.DefineField("_" + o.Key, o.Value, FieldAttributes.[Private])
С уважением.
Гораздо проще использовать System.Activator:
Activator.CreateInstance(YourType, ParramArrayOfYourVariablesForNEW)
Скажем, у меня есть класс (Test), который принимает одну строку в инициализации
Public Class Test
Public Sub New(byval MyString as string)
...
Вы можете создать новый экземпляр, как это:
Activator.CreateInstance(gettype(Test),"My String")
Эта строка:
Dim field As FieldBuilder = myType.DefineField("_" + o.Key, GetType(Integer), FieldAttributes.[Private])
должен быть заменен этим:
Dim field As FieldBuilder = myType.DefineField("_" + o.Key, o.Value, FieldAttributes.[Private])