2012-01-30 81 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