vb.net 在运行时动态创建类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26956824/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 18:28:57  来源:igfitidea点击:

Create Class dynamically at runtime

vb.netgenericsreflectiondynamic-class

提问by Vahid Farahmandian

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

我有一个这样的方法:(这是一个通用方法,DYNAMIC_CLASS_TYPE会根据情况更改为其他情况)

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.

我想根据查询的列创建一个动态类,然后传递类而不是DYNAMIC_CLASS_TYPE.

How can I do this?

我怎样才能做到这一点?

采纳答案by Vahid Farahmandian

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.

函数的返回值是我的自定义类的类型。

回答by Jacek_D73

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.

问候。

回答by Lunadix

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])

回答by Steve

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

更简单的方法是使用 System.Activator:

Activator.CreateInstance(YourType, ParramArrayOfYourVariablesForNEW)

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

所以说我有一个类 (Test) 在初始化中采用单个字符串

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

You could create a new instance like this:

您可以像这样创建一个新实例:

Activator.CreateInstance(gettype(Test),"My String")