CODE-將匿名型別陣列匯成CSV

工作的專案有個小需求,使用者羅列了一堆報表匯出需求,基上都是從現存LINQ資料集合以不同條件取出不同欄位。

我想到最簡便的做法是套用Where()查詢,依需求產生匿名型別

Select(o => new {
    欄位1 = o.PropA,
    欄位2 = o.PropB,
    欄位3 = o.PropC …
})

連欄位名稱都隨使用者指定,最後再將查詢結果轉為CSV,幾個步驟就搞定一項報表需求,進行量產。

基於以上構想,我需要一個能將任意匿名型別陣列或List自動轉成CSV的共用函數,挑戰點在於陣列元素型別未知,但這可難不倒C#,祭出Reflection就能輕鬆克服。

試寫範例如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
 
namespace AnonymousTypeListReflectionTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var ary = "Jeffrey,Darkthread,Geek".Split(',')
                .Select(o => new
                {
                    文字 = o,
                    長度 = o.Length
                }).ToArray();
            Console.Write(convToCsv(ary));
            Console.Read();
        }
        //將任意型別陣列輸出為CSV,第一列為標題列舉欄位名稱
        static string convToCsv(Array ary)
        {
            //取得陣列元素的型別
            Type elemType = ary.GetType().GetElementType();
            PropertyInfo[] props = elemType.GetProperties();
            StringBuilder sb = new StringBuilder();
            //第一列輸出屬性名稱
            sb.AppendLine(string.Join("\t", props.Select(o => o.Name).ToArray()));
            //藉由foreach巡迴每一元件,透過Refelction取出屬性值
            foreach (object elem in ary)
            {
                sb.AppendLine(string.Join("\t",
                    props.Select(o => Convert.ToString(o.GetValue(elem, null)))));
            }
            return sb.ToString();
        }
    }
}

實際寫完,程式遠比預期來得單純: 傳入參數時,將匿名型別陣列轉型成Array、GetElementType()可以找出陣列元素型別、Reflection GetProperties()跟PropertyInfo.GetValue()已是老把戲不用多說,至於分隔符號我選擇用Tab "\t"取代逗號,以省去處理屬性值內含逗號的麻煩。

就這樣,任意型別陣列轉CSV的函數就寫完囉~ 又到了感恩時刻,讓我們一起高呼: .NET好威呀!

歡迎推文分享:
Published 01 May 2013 07:21 AM 由 Jeffrey
Filed under: ,
Views: 7,419



意見

# Lonka said on 01 May, 2013 10:12 PM

您好!

這個方法去轉CSV真的很方便。

有個問題想問一下,您在文中有提到「連欄位名稱都隨使用者指定」,就是您提到的「依需求產生匿名型別」。

我想請問的就是要如何用程式動態的依照使用者需求產生匿名型別?

感謝

# Jeffrey said on 02 May, 2013 12:17 AM

to Lonka, 文中所提情境,主要在簡化使用者提了大量報表需求時的開發。若希望能做到不需事前提規格,100%即興演出,就得實做出動態LINQ查詢,方法蠻多的,我想最簡便的是透過Dynamic LINQ程式庫。[可參考: blog.miniasp.com/.../Introduce-LINQ-Dynamic-Query-Library.aspx]

# Lonka said on 02 May, 2013 01:50 AM

to Jeffrey, 謝謝你撥空回答我的問題,還費心的給了我一個很好的方向。Dynamic LINQ library確實能解決我的問題。感謝  :)

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<May 2013>
SunMonTueWedThuFriSat
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678
 
RSS
創用 CC 授權條款
【廣告】
twMVC

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication