6

I have a method like this: (this is a generic method, and DYNAMIC_CLASS_TYPE will be changed in situation to other situation)

Dim res = f.MyMethod(Of DYNAMIC_CLASS_TYPE)("select Id, Name from myTable")

I want to create a dynamic class, based on my query's columns and then pass the class instead of DYNAMIC_CLASS_TYPE.

How can I do this?

Vahid Farahmandian
  • 6,081
  • 7
  • 42
  • 62

4 Answers4

7

I finally succeeded in doing it. My Code is as:

 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, o.Value, 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

The return value of the function is a Type of my Custom Class.

Vahid Farahmandian
  • 6,081
  • 7
  • 42
  • 62
  • 1
    Great little code snippet! One question though: Is there any specific reason you're using `GetType(Integer)` for your fields? Otherwise it'd probably be a good idea to apply [**the already mentioned change**](https://stackoverflow.com/a/27499618). – Visual Vincent Aug 21 '17 at 18:23
2

There seems to be a bug. I think this line:

Dim field As FieldBuilder = myType.DefineField("_" + o.Key, GetType(Integer), FieldAttributes.[Private])

should look like this:

Dim field As FieldBuilder = myType.DefineField("_" + o.Key, o.Value, FieldAttributes.[Private])

Regards.

Jake Chasan
  • 6,290
  • 9
  • 44
  • 90
Jacek_D73
  • 21
  • 1
0

A much simpler way is to use the System.Activator:

Activator.CreateInstance(YourType, ParramArrayOfYourVariablesForNEW)

So say I have a class (Test) that takes a single string in the initialization

Public Class Test
    Public Sub New(byval MyString as string)
...

You could create a new instance like this:

Activator.CreateInstance(gettype(Test),"My String")
Steve
  • 5,585
  • 2
  • 18
  • 32
  • the problem is that we do not have even that Test class and we want to create it runtime – Vahid Farahmandian Nov 18 '14 at 10:16
  • You must have something somewhere that knows what it is. If you would rather get the type using a string, you can do this: `System.Reflection.Assembly.GetExecutingAssembly.GetType("WindowsApplication1.Test", True, True)` – Steve Nov 18 '14 at 15:32
  • 1
    I think my question was unclear and may be it is because of my bad english. Apologize for this. Your latest approach is not answer to my problem, because I need to CREATE the class at runtime. I mean I am going to introduce it's properties and fields and other elements all at runtime, and finally I am going to get it's type and do further operations. However I have reached an answer to this problem and I have shared it with all below. At the end I should thank you, for your great comments and tips and supports. ;-) – Vahid Farahmandian Nov 18 '14 at 16:02
-1

This line:

Dim field As FieldBuilder = myType.DefineField("_" + o.Key, GetType(Integer), FieldAttributes.[Private])

must to be replaced with this:

Dim field As FieldBuilder = myType.DefineField("_" + o.Key, o.Value, FieldAttributes.[Private])
Chewpers
  • 2,430
  • 5
  • 23
  • 30
Lunadix
  • 1
  • 1