如何使用GetType和GetFields?

时间:2016-06-07 12:21:48

标签: vb.net visual-studio gettype

我正在更新程序,大约有40个课程。我需要创建一个函数,它将两个类型对象列表作为参数。两个列表中只有一个项目(在进行任何更改之前的项目版本,以及更改发生之后)。我使用这些对象创建一个对象来实现UNDO按钮。有了这些参数,我需要得到每个参数的类型,并确保它们匹配,如果没有,那么出现问题。接下来我需要阅读字段/属性/成员(不确定要选择什么),然后将它们相互比较并找到更改的内容,以便将其设置为项目描述。我不想跟踪整个代码并为每个代码添加特定的功能,我知道必须有一种方法来执行此操作。我已经创建了这个小型模拟程序,该程序对我正在尝试的内容起作用。我可以从列表中的对象中获取类类型,但我不知道如何获取字段或其他任何内容。

我正在使用具有实体框架的大型数据库。 也使用VB.NET!
谢谢您的帮助! 这是通用程序的代码:

Imports System.Reflection

模块模块1

Sub Main()


    Dim Myself As New Human("Matthew", "Cucco", Now, "Blonde", 19, False)
    Dim NotMe As New Human("Jake", "Cucco", Now, "Blonde", 19, False)
    Dim Him As New Employee("Matt", "Cucco", Now, "Blonde", 19, False, 215, "LuK", True)
    Dim Her As New Customer("Jessie", "Keller", Now, "Blonde", 19, True, 25, "Cereal", "me@gmail.com")

    Dim ListofPeople As IList(Of Object) = {Myself, NotMe, Him, Her}
    Dim ListofPeople2 As IList(Of Object) = {Myself, NotMe, Him, Her}


    ObjectsAreSameClass(ListofPeople, ListofPeople2)
    Console.ReadKey()


End Sub

Private Function ObjectsAreSameClass(object1 As IList(Of Object), object2 As IList(Of Object)) As Boolean

    Dim ObjectType As Type = object1.First.GetType()
    Dim AreSameClass As Boolean = Nothing
    Console.WriteLine(ObjectType.ToString)

    If (object1.First.GetType() = object2.First.GetType()) Then
        AreSameClass = True
        Console.WriteLine("Object1 is of type: " + object1.First.GetType().Name)
        Console.WriteLine("Object2 is of type: " + object2.First.GetType().Name)
        If (object1.First.GetType().Name = "Human") Then
            Console.WriteLine("Yep this works")
        End If


    Else
        AreSameClass = False
        Console.WriteLine("Object1 is of type: " + object1.First.GetType().Name)
        Console.WriteLine("Object2 is of type: " + object2.First.GetType().Name)
        If (object1.First.GetType().Name = "Human") Then
            Console.WriteLine("Yep this works")
            Console.WriteLine(object1.First.GetType().GetFields().ToString)
        End If

    End If

    Dim MyField As PropertyInfo() = ObjectType.GetProperties()
    Dim i As Integer
    For i = 0 To MyField.Length - 1
        Console.WriteLine(MyField(i).ToString)
    Next i

    Console.WriteLine("Objects are equal? t/f : " + AreSameClass.ToString)

    Return AreSameClass
End Function


Public Class Human

    Public FirstName As String
    Public LastName As String
    Public Birthdate As Date
    Public HairColor As String
    Public Age As Integer
    Public Gender As Boolean   'False for male, true for female




    Public Sub New()

        FirstName = ""
        LastName = ""
        Birthdate = Now
        HairColor = ""
        Age = 0
        Gender = False

    End Sub

    Public Sub New(f As String, l As String, b As Date, h As String, a As Integer, g As Boolean)

        FirstName = f
        LastName = l
        Birthdate = b
        HairColor = h
        Age = a
        Gender = g

    End Sub

End Class


Public Class Employee
    Inherits Human

    Dim EmployeeId As Integer
    Dim PlaceOfEmployment As String
    Dim IsManager As Boolean

    Public Sub New()
        MyBase.New()
        EmployeeId = 0
        PlaceOfEmployment = ""
        IsManager = False
    End Sub

    Public Sub New(f As String, l As String, b As Date, h As String, a As Integer, g As Boolean, i As Integer, p As String, m As Boolean)
        MyBase.New(f, l, b, h, a, g)
        EmployeeId = i
        PlaceOfEmployment = p
        IsManager = m
    End Sub


End Class




Public Class Customer
    Inherits Human
    'used for testing

    Dim IdNumber As Integer
    Dim FavoriteItem As String
    Dim email As String
    Public Sub New()
        MyBase.New()
        IdNumber = 0
        FavoriteItem = ""
        email = ""
    End Sub

    Public Sub New(f As String, l As String, b As Date, h As String, a As Integer, g As Boolean, i As Integer, fav As String, e As String)
        MyBase.New(f, l, b, h, a, g)
        IdNumber = i
        FavoriteItem = fav
        email = e
    End Sub


End Class

结束模块

目前显示:

TestProject.Module1+Human
Object1 is of type: Human
Object2 is of type: Human
Yep this works
Objects are equal? t/f : True

另外作为参考,这是我将要实现的主要程序:

Function NewItem(Before As IEnumerable(Of Object), After As IEnumerable(Of Object), ObjectType As String)

    ObjectsAreSameClass(Before, After, ObjectType)  'Check if objects are same class

    Dim BeforeFields() As FieldInfo = GetFieldData(Before)  'gets all field info, saves to an array
    Dim AfterFields() As FieldInfo = GetFieldData(After)

    'Now check and make sure the objects are not the same
    Dim ThisChanged As FieldInfo
    If (ObjectValuesAreEqual(BeforeFields, AfterFields) = True) Then
        'These objects did not not change
        ThisChanged = Nothing
    Else
        'Change occured, find out where
        ThisChanged = FindWhatChanged(BeforeFields, AfterFields)
    End If


    'Create a new UndoRedo item and give it these values
    Dim UndoRedoNow As New ClsUndoRedo
    UndoRedoNow.BeforeObject = Before.Single
    UndoRedoNow.AfterObject = After.Single
    UndoRedoNow.ObjectCounter += 1
    UndoRedoNow.WhatChanged = ThisChanged

    If WhatGroupChanged.isDeleted Then
        UndoRedoNow.WhatAction = Before.Single.GetType().ToString + " item was Deleted"
    ElseIf WhatGroupChanged.isNew Then
        UndoRedoNow.WhatAction = After.Single.GetType().ToString + " item was created"
    ElseIf WhatGroupChanged.isChanged Then
        UndoRedoNow.WhatAction = After.Single.GetType().ToString + " item was changed"
    End If
    UndoRedoNow.WhatGroupChanged.isRedo = False 'Make sure it is not a redo object

    'Now add object to list
    ChangeLog.Add(UndoRedoNow)

    Return Nothing
End Function


Private Function ObjectsAreSameClass(before As IEnumerable(Of Object), after As IEnumerable(Of Object), WhatType As String) As Boolean

    Dim AreSameClass As Boolean = False

    Try
        If (before.Single.GetType() = after.Single.GetType() Or (before Is Nothing) Or (after Is Nothing)) Then
            'Objects are of the same class or nothing
            If before Is Nothing Then
                WhatGroupChanged.isNew = True  'New item
            ElseIf after Is Nothing Then
                WhatGroupChanged.isDeleted = True  'Deleted item
            Else
                WhatGroupChanged.isChanged = True  'item was changed
            End If
            AreSameClass = True

        End If

    Catch
        'Need to raise error

    End Try
    Return AreSameClass
End Function

''' <summary>
''' This function will return all of the fields for a certain class as well as the data stored in them
''' </summary>
''' <param name="list"></param>
''' <returns></returns>
Public Shared Function GetFieldData(ByVal list As IList(Of Object)) As FieldInfo()

    Dim fields() As FieldInfo = list.Single.GetType().GetFields()

    Return fields

End Function

''' <summary>
''' This function will check that the values in the datafields are not equal
''' </summary>
''' <param name="Before"></param>
''' <param name="After"></param>
''' <returns></returns>
Private Function ObjectValuesAreEqual(Before() As FieldInfo, After() As FieldInfo) As Boolean

    Dim isEqual As Boolean = New Boolean    'This will keep track of if the elements are equal or not

    For index As Integer = 0 To (Before.Count - 1)
        If Before.ElementAt(index).GetValue(Before.ElementAt(index)).Equals(After.ElementAt(index).GetValue(After.ElementAt(index))) Then
            'They are equal so set to true
            isEqual = True

        Else
            'They are not equal so set to false and return
            isEqual = False
            Return isEqual

        End If
    Next
    Return isEqual
End Function

Private Function FindWhatChanged(Before() As FieldInfo, After() As FieldInfo) As FieldInfo
    Dim ThisIsChange As FieldInfo
    For index As Integer = 0 To (Before.Count - 1)
        If Before.ElementAt(index).GetValue(Before.ElementAt(index)).Equals(After.ElementAt(index).GetValue(After.ElementAt(index))) Then
            ThisIsChange = After.ElementAt(index)
            Return ThisIsChange

        Else
            'Raise error
        End If
    Next

End Function

1 个答案:

答案 0 :(得分:1)

使用未知类型时保留类型信息的正确方法是编写泛型函数(如果需要,还可以编写泛型类,结构等)。

在一个完美的世界中,永远不需要使用GetType

通用函数如下所示:

Public Function MyGenericFunction(Of T)(myArg as T) as Integer
    ' do something with myArg1, myArg2 ... without knowing their exact type
    Return 0
End Function

' or with multiple types
Public Function MyGenericFunction2(Of T1, T2, ... )(myArg1 as T1, myArg2 as T2, ...) as T1()
    ' do something with myArg1, myArg2 ... without knowing their exact type
    Return { myArg1 }
End Function

当您调用这些函数时,通常会从您传递的参数中自动推导出泛型类型。如果他们无法猜到,您需要明确注释类型,如下所示:

Dim x = MyGenericFunction(Of SomeClass1)(foo)
Dim x = MyGenericFunction(Of SomeClass2)(foo)

完整指南:https://msdn.microsoft.com/en-us/library/w256ka79.aspx

但是,如果您需要处理具有相同功能的特定类型,那么您想要使用的是一个更窄的工具:重载,或者更具技术性< strong>参数多态。

这意味着,您需要提供相同功能的两个(或更多)不同定义(=具有相同名称),接受不同类型的参数。

一个简单的例子:

Public Class MyClass1
    Public Foo1 As String  = "foo1"
End Class

Public Class MyClass2
    Public Foo2 As String = "foo2"
End Class

Public Sub MyFunction(arg as MyClass1)
    Console.WriteLine(arg.Foo1)
End Sub

Public Sub MyFunction(arg as MyClass2)
    Console.WriteLine(arg.Foo2)
End Sub

Dim x as Object

' let's give x a random value of either MyClass1 or MyClass2,
' and we don't know in advance which one
If DateTime.Today.DayOfWeek = DayOfWeek.Tuesday Then 
  x = new MyClass1
Else
  x = new MyClass2
End If

' the program will automatically invoke the correct function based on x's value, and print either "foo1" or "foo2"
MyFunction(x)