我目前正在使用包含数据的文件。
数据可以在各种类中,并且这些类在同一文件中定义。
我目前能够将类输出到json,并且我能够将数据作为json转换为这些类
问题是我希望能够动态创建一个类来处理数据,而不是简单地将其作为文件打印出来。
班级示例:
Class id:4 - name Item
public Int id
public I18N nameId
public Int typeId
public I18N descriptionId
public Int iconId
public Int level
public Int realWeight
public Bool cursed
public Int useAnimationId
public Bool usable
public Bool targetable
public Bool exchangeable
public Double price
public Bool twoHanded
public Bool etheral
public Int itemSetId
public String criteria
public String criteriaTarget
public Bool hideEffects
public Bool enhanceable
public Bool nonUsableOnAnother
public Int appearanceId
public Bool secretRecipe
public Int recipeSlots
public vector<UInt> recipeIds
public vector<UInt> dropMonsterIds
public Bool bonusIsSecret
public vector<EffectInstance> possibleEffects
public vector<UInt> favoriteSubAreas
public Int favoriteSubAreasBonus
public Int craftXpRatio
public Bool needUseConfirm
public Bool isDestructible
public vector<vector<Double>> nuggetsBySubarea
public vector<UInt> containerIds
public vector<vector<Int>> resourcesBySubarea
类型是从具有枚举的Uint定义的:
Public Enum GameDataTypeEnum
Int = -1
Bool = -2
[String] = -3
[Double] = -4
I18N = -5
UInt = -6
Vector = -99
End Enum
为了解决这个问题,我尝试将枚举类型转换为vb.net类型,例如:
Dim myType1 As Type = Type.GetType("System.Int32")
然后我尝试使用Activator.CreateInstance,如下所示:
Dim Type1 As Type = Type.GetType("System.String")
Dim Type2 As Type = Type.GetType("System.Int32")
Dim dictType As Type = GetType(Dictionary(Of , )).MakeGenericType(Type1, Type2)
Dim dict = Activator.CreateInstance(dictType)
dict.add("test", 32)
Console.WriteLine(dict.Item("test"))
这很好但是回顾这个解决方案它不可行,因为类有不同的类型。你会看到从文件中创建类并动态生成它们吗?
最糟糕的情况我可以手动生成所有类但是有很多类并且需要花费很多时间
文森特的解决方案可以解决一个小问题。
当我读取文件时,字段可能包含另一个字段,这些字段称为向量,可以表示为:(包含值)列表
现在我只需这样做:
For Each field As GameDataField In classDefinition.Value.Fields
Console.WriteLine(field.fieldName & " --- " & testcast(getFieldTypeString(field)))
Console.WriteLine(field.fieldName & " --- " & field.fieldType)
ClassProperties.Add(field.fieldName, Type.GetType(testcast(getFieldTypeString(field))))
Next
我的testcast()
函数只返回一个字符串,将枚举转换为正确的格式,如Int
到System.Int32
对于我的getFieldTypeString,我有:
If isPrimitiveFieldType(field) Then
Return getPrimitiveFieldTypeString(field)
Else
Return getCompositeFieldTypeString(field)
End If
原语给出:
Private Function getPrimitiveFieldTypeString(field As GameDataField) As String
Return If(field.fieldType > 0, classDefinitions(CInt(field.fieldType)).Name, field.fieldType.ToString())
End Function
Composite给出:
Private Function getCompositeFieldTypeString(field As GameDataField) As String
Dim compositeFieldTypeBuilder As New StringBuilder()
compositeFieldTypeBuilder.Append("System.Collections.Generic.List(Of ")
If getFieldTypeString(field.innerField) = "UInt" Then
compositeFieldTypeBuilder.Append("UInt32)")
ElseIf getFieldTypeString(field.innerField) = "Int" Then
compositeFieldTypeBuilder.Append("Integer)")
Else
compositeFieldTypeBuilder.Append(getFieldTypeString(field.innerField)).Append(")")
End If
Return compositeFieldTypeBuilder.ToString()
End Function
如何将属性添加到ClassProperties以表示:
List of a List of a Type
答案 0 :(得分:1)
正如评论中已经提到的this answer(以及this fix)将帮助您动态创建类。
要获取/设置这些类的属性,我们可以创建两个使用反射的扩展方法,以便按名称访问属性getters / setter:
Imports System.Runtime.CompilerServices
Public Module Extensions
''' <summary>
''' Uses Reflection to get the value of the specified property.
''' </summary>
''' <param name="Instance">The object instance which's property to access.</param>
''' <param name="PropertyName">The name of the property which's value to get.</param>
''' <param name="Arguments">Arguments to pass along to the property method (if any).</param>
''' <remarks></remarks>
<Extension()> _
Public Function GetProperty(ByVal Instance As Object, ByVal PropertyName As String, Optional ByVal Arguments As Object() = Nothing) As Object
Return Instance.GetType().GetProperty(PropertyName).GetValue(Instance, Arguments)
End Function
''' <summary>
''' Uses Reflection to set the value of the specified property.
''' </summary>
''' <param name="Instance">The object instance which's property to access.</param>
''' <param name="PropertyName">The name of the property which's value to set.</param>
''' <param name="Value">The new value to give the property.</param>
''' <param name="Arguments">Arguments to pass along to the property method (if any).</param>
''' <remarks></remarks>
<Extension()> _
Public Sub SetProperty(ByVal Instance As Object, ByVal PropertyName As String, ByVal Value As Object, Optional ByVal Arguments As Object() = Nothing)
Instance.GetType().GetProperty(PropertyName).SetValue(Instance, Value, Arguments)
End Sub
End Module
注意:强>
由于您似乎无法在
System.Object
上使用扩展程序,因此您只需正常调用它们:Extensions.SetProperty(MyObject, "MyProperty", MyValue)
但是,对于任何
System.Object
的任何内容,您都可以像通常那样使用这些扩展方法:Button1.SetProperty("Text", "Click me!")
现在您可以像这样使用它们:
'Just a quick mockup of properties.
Dim ClassProperties As New Dictionary(Of String, Type) From {
{"name", Type.GetType("System.String")},
{"id", Type.GetType("System.Int32")},
{"hasCar", Type.GetType("System.Boolean")}
}
'Create the class type.
Dim CustomClass As Type = CreateClass("Person", ClassProperties)
'Create an instance of the class.
Dim MyPerson As Object = Activator.CreateInstance(CustomClass)
'Modify its properties.
Extensions.SetProperty(MyPerson, "name", "John Doe")
Extensions.SetProperty(MyPerson, "id", 12345)
Extensions.SetProperty(MyPerson, "hasCar", True)
MessageBox.Show( _
String.Join(Environment.NewLine, {Extensions.GetProperty(MyPerson, "name"), _
Extensions.GetProperty(MyPerson, "id"), _
Extensions.GetProperty(MyPerson, "hasCar")}), _
"", MessageBoxButtons.OK, MessageBoxIcon.Information)
利润!