Как написать методы расширения для анонимных типов? - PullRequest
4 голосов
/ 30 января 2012

Я пытаюсь создать метод расширения 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)
    {

Делаете ли вывидите, что я делаю не так?

Ответы [ 2 ]

12 голосов
/ 30 января 2012

Вы должны указать параметр общего типа в сигнатуре метода:

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
    }
}
2 голосов
/ 30 января 2012

Можно делать то, что вы пытаетесь сделать, используя отражение.Однако производительность будет несколько хуже, чем при написании неуниверсального кода.

Вот полный пример кода:

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();
        }
    }
}
...