2012-01-30 82 views
4

我想爲我的可枚舉列表創建一個CSV擴展方法,我很難過。以下是我創造了我簡單枚舉列表:如何編寫匿名類型的擴展方法?

var CAquery = from temp in CAtemp 
join casect in CAdb.sectors 
on temp.sector_code equals casect.sector_code 
select new 
{  
    CUSIP = temp.equity_cusip, 
    CompName = temp.company_name, 
    Exchange = temp.primary_exchange  
}; 

CAquery.WriteToCSVFile(); 

這是我在創造一個擴展方法(我認爲這是錯誤的),這樣做的遠:

public static class CSVExtensions 
{   
    public static void WriteToCSVFile(this IEnumerable<T> myList) 
    { 

你明白我米做錯了嗎?

回答

10

您必須指定在方法簽名的泛型類型參數:

public static class CSVExtensions 
{   
    public static void WriteToCSVFile<T>(this IEnumerable<T> myList) 
    { 
     //your code here 
    } 
} 

你真正想要寫,應該在任何IEnumerable<T>工作,或者是你的類型更具體的擴展方法?如果後面的情況是這樣,你應該用你想要支持的類型替換T(或者添加足夠的約束)。

編輯:

在評論光 - 你應該投射到一類,而不是在查詢匿名類型 - 那麼你可以使用這種特殊類型的擴展方法,即:

class CompanyTicker 
{ 
    public string CUSIP {get;set;} 
    public string CompName {get;set;} 
    public string Exchange {get;set;} 
} 

現在你的查詢可以是:

var CAquery = from temp in CAtemp 
join casect in CAdb.sectors 
on temp.sector_code equals casect.sector_code 
select new CompanyTicker 
{  
    CUSIP = temp.equity_cusip, 
    CompName = temp.company_name, 
    Exchange = temp.primary_exchange  
}; 

而且你的擴展方法(現在並不需要是通用)變成:

public static class CSVExtensions 
{   
    public static void WriteToCSVFile(this IEnumerable<CompanyTicker> myList) 
    { 
     //your code here 
    } 
} 
+0

是後者。我的類型更具體。我認爲我的問題是,我不知道什麼類型是完全可以使用的。當我顯示類型時,我得到:'System.Linq.Enumerable + d__81'。不給我一個清晰的想法。 – 2012-01-30 17:28:58

+0

因爲您使用的是匿名類型,所以無法創建您想要的特定通用實現。如果將這些值填入一個衆所周知的類中,則可以使用BrokenGlass的正確解決方案。 – 2012-01-30 17:34:23

+0

@inquisitive_one:更新了答案 – BrokenGlass 2012-01-30 17:54:59

1

它可以做你正在嘗試使用反射。但是,如果編寫非泛型代碼,性能會有所下降。

下面是一個完整的代碼示例:

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Reflection; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var seq = 
     Enumerable.Range(0, 100) 
      .Select(i => new { Name = "Item" + i, Value = i }) 
      ; 

     seq.WriteCsv(Console.Out); 
     Console.ReadLine(); 
    } 
} 

public static class CsvExtension 
{ 

    public static void WriteCsv<T>(this IEnumerable<T> seq, TextWriter writer) 
    { 
     var type = typeof(T); 

     MethodInfo[] getters = type.GetProperties().Select(pi => pi.GetGetMethod()).ToArray(); 


     // only supporting simple properties 
     // indexer properties will probably fail 
     var args = new object[0]; 

     foreach (var item in seq) 
     { 
      for (int i = 0; i < getters.Length; i++) 
      { 
       if (i != 0) 
        writer.Write(","); 

       Object value = getters[i].Invoke(item, args); 
       var str = value.ToString(); 

       if (str.Contains(",") || str.Contains("\"")) 
       { 
        var escaped = str.Replace("\"", "\\\""); 
        writer.Write("\""); 
        writer.Write(escaped); 
        writer.Write("\""); 
       } 
       else 
       { 
        writer.Write(str); 
       } 
      } 


      writer.WriteLine(); 
     } 
    } 
} 
+1

此外,如果性能問題,您可以使用Reflection.Emit或System.Linq.Expressions中的類來運行時編譯方法。您將在運行時支付編譯代碼的費用一次,但對該方法的任何調用將與您手寫代碼一樣快。然而,生成該方法的代碼有點複雜。 – MarkPflug 2012-01-30 18:10:56