【问题标题】:Create Class dynamically at runtime在运行时动态创建类
【发布时间】:2014-11-16 12:18:35
【问题描述】:

我有一个这样的方法:(这是一个泛型方法,DYNAMIC_CLASS_TYPE会根据情况改成其他情况)

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

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

我该怎么做?

【问题讨论】:

  • 你应该看看匿名类型。 (和 linq2SQL)

标签: vb.net generics reflection dynamic-class


【解决方案1】:

我终于成功了。我的代码如下:

 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

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

【讨论】:

  • 很棒的小代码sn-p!但是有一个问题:您在字段中使用GetType(Integer) 是否有任何具体原因?否则,申请the already mentioned change 可能是个好主意。
【解决方案2】:

似乎有一个错误。我认为这一行:

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

应该是这样的:

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

问候。

【讨论】:

    【解决方案3】:

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

    Activator.CreateInstance(YourType, ParramArrayOfYourVariablesForNEW)
    

    假设我有一个类 (Test),它在初始化时采用单个字符串

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

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

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

    【讨论】:

    • 问题是我们甚至没有那个 Test 类,我们想在运行时创建它
    • 你必须在某个地方知道它是什么。如果您希望使用字符串获取类型,可以这样做:System.Reflection.Assembly.GetExecutingAssembly.GetType("WindowsApplication1.Test", True, True)
    • 我认为我的问题不清楚,可能是因为我的英语不好。为此道歉。您的最新方法不能解决我的问题,因为我需要在运行时创建类。我的意思是我将在运行时介绍它的属性和字段以及其他元素,最后我将获取它的类型并进行进一步的操作。但是,我已经找到了这个问题的答案,并与下面的所有人分享了它。最后,我要感谢您,感谢您提供的出色的 cmets 以及提示和支持。 ;-)
    【解决方案4】:

    这一行:

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

    必须替换为:

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

    【讨论】:

      猜你喜欢
      • 2010-11-14
      • 1970-01-01
      • 1970-01-01
      • 2020-05-04
      • 1970-01-01
      • 1970-01-01
      • 2011-02-28
      • 2012-04-08
      • 2017-09-24
      相关资源
      最近更新 更多