Pages - Menu

2017年1月17日 星期二

VB.NET +LinqToCSV+泛型+反射

前面兩項vb.net+LinqToCSV的應用,

沒什麼困難。但後面因為不同的設備,要用到不同的class但邏輯都一樣。

想說就來用泛型好了,結果…..燒的我一個頭兩個大。

泛型用完,還要用反射來動態取class的Property燒的我頭又更大了。

泛型+反射 還有很多未解的問題,還需慢慢研究。

此文章會用到徐大寫的LinqToCSV介紹

但我用的是vb.net,為了以後的人…...

基本的語法會像這樣子

Dim cv As CsvFileDescription = New CsvFileDescription() With
    {
        .SeparatorChar = ",",
        .FirstLineHasColumnNames = False,
        .EnforceCsvColumnAttribute = True,
        .IgnoreUnknownColumns = True    '//該死的選項害我卡關卡了整整4個小時
    }
Dim cc As CsvContext = New CsvContext()
Dim Stream As FileStream = New FileStream(ReadFiles, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
Using reader As StreamReader = New StreamReader(Stream, System.Text.Encoding.UTF8)

    Dim pp = cc.Read(Of disCharge12)(reader, cv)
End Using

Read後面會接class,讓csv能夠跟他對應。

要注意的是 IgonreUnknowColumns ,

有另一個長得很像的參數IgnoreTrailingSeparatorChar

要忽略不同的col預設是false,如果沒設true,要麻就是你的class寫的剛剛好,

一比一的都有對到。不然真的抓不到原因。

下面是泛型+反射設定欄位

 

Private Function getCSVData(Of T As {Class, New})(ByVal ReadFiles As String, ByVal col As T)

        Dim CountsZero As Integer = 0
        Try
            Dim cv As CsvFileDescription = New CsvFileDescription() With
                {
                    .SeparatorChar = ",",
                    .FirstLineHasColumnNames = False,
                    .EnforceCsvColumnAttribute = True,
                    .IgnoreUnknownColumns = True    '///////該死的選項害我卡關卡了整整4個小時
                }
            Dim cc As CsvContext = New CsvContext()
            Dim Stream As FileStream = New FileStream(ReadFiles, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
            Using reader As StreamReader = New StreamReader(Stream, System.Text.Encoding.UTF8)

                Dim pp = cc.Read(Of T)(reader, cv)
                Dim list = pp.ToList              

                For Each ss In list

                    '此段為建立一個新的class,但目前只需要將原始的檔案名稱加上fileName的值
                    'Dim oTemp As Object = System.Activator.CreateInstance(System.Type.GetType(className))
                    Dim uTemp As Object = ss
                    Dim uType As Type = ss.GetType
                    Dim uProperty As Reflection.PropertyInfo = uType.GetProperty("fileName")

                    uProperty.SetValue(uTemp, FileNames)
                    'msg(ss.ToString)
                Next
                Return list
            End Using
End Function

 

使用方式

Dim condition = 3
Dim list
If condition = 3 Then
    list = getCSVData(Of disCharge3)(ReadFiles, New disCharge3)
Else
    list = getCSVData(Of disCharge16)(ReadFiles, New disCharge16)
End If

Readfile 是檔案位置

值取出來後,如果直接指定類別,可以直接印出。

For Each pp As disCharge3 In list
    msg(pp.fileName)
Next

如果不想指定類別,就仍然必須使用反射的方式取得要輸出的名稱

For Each pp  In list
    '利用反射的方式取值
    Dim uTemp As Object = pp
    Dim uType As Type = pp.GetType
    Dim uProperty As Reflection.PropertyInfo = uType.GetProperty("fileName")
    Dim fileName = uProperty.GetValue(uTemp)
    msg(fileName)
Next

class的名稱結構像這樣

Public Class disCharge3
    Inherits charge
    <CsvColumn(FieldIndex:=1)>
    Public Property batteryType As String
    <CsvColumn(FieldIndex:=2, CanBeNull:=True)>
    Public Property batteryLot As String
    <CsvColumn(FieldIndex:=3, CanBeNull:=True)>
    Public Property batteryAmp As String
    <CsvColumn(FieldIndex:=4, CanBeNull:=True)>
    Public Property status As String
    <CsvColumn(FieldIndex:=5, CanBeNull:=True)>
    Public Property cstype As String
    <CsvColumn(FieldIndex:=6, CanBeNull:=True)>
    Public Property fileName As String

End Class

沒有留言:

張貼留言