string.Join() works nice for creating a string from a list/collection with separator. We can use any string as separator and also as parameter we have to pass array of values. For example we have a collection of columns names of a table and for creating SQL select statement I need to create a statement with comma separation of those columns names. Code here
var collection = new string[] {"Id", "CountryName", "ISOName", "PrintableName"}; var joinOfCollection = string.Join(",", collection);
This will return you a string value with comma separation of those collection.
Id,CountryName,ISOName,PrintableName
But the where clause statement will be WHERE
Id =@Id
AND
ISO=@ISO
here separator is AND but in string.Join I can not give any format like “{0}=@{0}”. Also with LINQ aggregate it is difficult for giving any separator. For that I have to use substring() operation after that or have to give checking inside every iteration. If I could use string.Format() then I could append format while joining string collection. The code for solving this problem will be
public static string JoinFormat<T>(this T[] values, string separator, string format)
{
if (values == null)
throw new ArgumentNullException("values");
if (values.Length == 0 || values[0] == null)
return string.Empty;
if (separator == null)
separator = string.Empty;
var stringBuilder = new StringBuilder();
string str1 = values[0].ToString();
if (str1 != null)
stringBuilder.AppendFormat(format, str1);
for (int index = 1; index < values.Length; ++index)
{
stringBuilder.Append(separator);
if (values[index] != null)
{
string str2 = values[index].ToString();
if (str2 != null)
stringBuilder.AppendFormat(format, str2);
}
}
return stringBuilder.ToString();
}
This will work fine for array of data and formatting will work like this :
var columnsList = new int[] { 1, 2, 3 }; var joinFormat = columnsList.JoinFormat(",", "{0}=@{0}");
But for custom class collection like I have collection of country class and I wanted to pass the data as XML attribute.
public class Country { public string Name { get; set; } public string ISO { get; set; } }
And we have collection of data like
var countryList = new List<Country> { new Country {Name = "United State", ISO = "US"}, new Country {Name = "United Kingdom", ISO = "GB"}, new Country {Name = "Bangladesh", ISO = "BD"} };
Here above extension function will not work as this does not support collection of custom class. For that I have used Action delegate so that user can define own format. Then this will support both primitive types collections and custom type collections.
public static string JoinFormat<T>(this IEnumerable<T> values, string separator, Func<T, string> action) { if (values == null) throw new ArgumentNullException("values"); var enumerator = values.GetEnumerator(); var stringBuilder = new StringBuilder(); if (enumerator.MoveNext() == false || enumerator.Current == null) { return string.Empty; } stringBuilder.Append(action(enumerator.Current)); while (enumerator.MoveNext()) { stringBuilder.Append(separator); if (enumerator.Current != null) { stringBuilder.Append(action(enumerator.Current)); } } return stringBuilder.ToString(); }
This is solution for where class also making XML type elements. Lets call this method for both cases :
Where class :
var columnList = new List<int> { 1, 2, 3 }; var joinFormat = columnList.JoinFormat(",", c => string.Format("{0}=@{0}", c));
Also for XML format for Country class collection will be
var countryList = new List<Country> { new Country {Name = "United State", ISO = "US"}, new Country {Name = "United Kingdom", ISO = "GB"}, new Country {Name = "Bangladesh", ISO = "BD"} }; var joinFormat = countryList.JoinFormat("", country => string.Format(@"<Country Name=""{0}"" ISO=""{1}""></Country>", country.Name, country.ISO) );
I am using this solution for generating SQL clauses like Select clause, Order by clause, Where clause, Update clause. I will upload solution with this code and unit tests.
Source Code link http://dl.dropbox.com/u/20275838/JoinWithFormat.zip
No comments:
Post a Comment