Как передать динамически создаваемый тип в функцию? - PullRequest
0 голосов
/ 29 апреля 2020

Я пытаюсь получить данные из запроса SQL и преобразовать их в список объектов. От SQL каждый раз я получаю набор данных с переменным количеством столбцов и разными именами столбцов. Поэтому я пытаюсь написать универсальный код для получения и преобразования этого набора данных.

Dim MySqlStr As String
MySqlStr = "exec someStoredProcedure "
Try
    MyAdapter = New SqlClient.SqlDataAdapter(MySqlStr, Declarations.MyNETConnStr)
    MyAdapter.SelectCommand.CommandTimeout = 600
    MyAdapter.Fill(MyDs)
    '-----Dictionary of columns with types
    Dim MyDict = New Dictionary(Of String, Type)
    For i As Integer = 0 To MyDs.Tables(0).Columns.Count - 1
        MyDict.Add(MyDs.Tables(0).Columns(i).ToString, MyDs.Tables(0).Columns(i).DataType)
    Next

    '----Dynamic type
    Dim MyCls As Type
    MyCls = CreateClass("DynClass", MyDict)
    Dim MyObj As Object = Activator.CreateInstance(MyCls)

    '-----Use newtonsoft
    Dim json As String = JsonConvert.SerializeObject(MyDs, Formatting.Indented)

    '-----here is a problem
    '-----I am tryin to deserialize json
    '-----but get a message that MyCls is not defined
    '-----how to pass dynamically created type to function correctly?
    Dim jsonData = JsonConvert.DeserializeObject(Of List(Of MyCls))(json)

    SfDataGrid2.DataSource = jsonData
Catch ex As Exception
End Try

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 And TypeAttributes.Class)
        'Dim getSetAttr As MethodAttributes = MethodAttributes.Public And MethodAttributes.SpecialName And MethodAttributes.HideBySig
        Dim getSetAttr As MethodAttributes = MethodAttributes.Public
        myType.DefineDefaultConstructor(MethodAttributes.Public)

        For Each o In properties
            Dim prop As PropertyBuilder = myType.DefineProperty(o.Key, PropertyAttributes.HasDefault, o.Value, Type.EmptyTypes)
            Dim field As FieldBuilder = myType.DefineField("_" + o.Key, o.Value, FieldAttributes.Private)

            Dim getter As MethodBuilder = myType.DefineMethod("get_" + o.Key, getSetAttr, o.Value, Type.EmptyTypes)
            Dim getterIL As ILGenerator = getter.GetILGenerator()
            getterIL.Emit(OpCodes.Ldarg_0)
            getterIL.Emit(OpCodes.Ldfld, field)
            getterIL.Emit(OpCodes.Ret)
            prop.SetGetMethod(getter)

            Dim setter As MethodBuilder = myType.DefineMethod("set_" + o.Key, getSetAttr, 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.SetSetMethod(setter)
        Next


        Return myType.CreateType()
    End Function

Пожалуйста, помогите с этим

...