I'm trying to create a CSV extension method for my enumerable list and I'm stumped. Here's how I created my simple enumerated list:
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();
This is what I have done so far in creating an extension method (which I think is wrong):
public static class CSVExtensions
{
public static void WriteToCSVFile(this IEnumerable<T> myList)
{
Do you see what I'm doing wrong?
An extension method must be defined in a top-level static class. An extension method with the same name and signature as an instance method will not be called. Extension methods cannot be used to override existing methods. The concept of extension methods cannot be applied to fields, properties or events.
Extension methods cannot access private variables in the type they are extending.
Anonymous types are class types that derive directly from object , and that cannot be cast to any type except object . The compiler provides a name for each anonymous type, although your application cannot access it.
You are allowed to use an anonymous type in LINQ. In LINQ, select clause generates anonymous type so that in a query you can include properties that are not defined in the class.
You have to specify the generic type parameter in the method signature:
public static class CSVExtensions
{
public static void WriteToCSVFile<T>(this IEnumerable<T> myList)
{
//your code here
}
}
Are you truly trying to write an extension method that should work on any IEnumerable<T>
or is your type more specific? If the later is the case you should replace T
with the type you want to support (or add sufficient constraints).
Edit:
In light of comments - you should project to a class instead of an anonymous type in your query - then you can use an extension method for this particular type, i.e.:
class CompanyTicker
{
public string CUSIP {get;set;}
public string CompName {get;set;}
public string Exchange {get;set;}
}
Now your query can be:
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
};
And your extension method (which now doesn't need to be generic) becomes:
public static class CSVExtensions
{
public static void WriteToCSVFile(this IEnumerable<CompanyTicker> myList)
{
//your code here
}
}
It is possible to do what you are trying to do using reflection. The performance is going to be somewhat worse than if you write non-generic code however.
Here is a complete code sample:
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();
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With