你最喜欢的C#扩展方法是什么? (codeplex.com/extensionoverflow)
让我们列出你发布你的优秀和最喜欢的扩展方法的答案。
要求是必须发布完整的代码,以及如何使用它的例子和解释。
基于对这个主题的高度兴趣,我已经在Codeplex上设置了一个名为extensionoverflow的开源项目。
请将您的答案标记为Codeplex项目中的代码。
请发布完整的源代码,而不是链接。
Codeplex新闻:
24.08.2010 Codeplex页面现在位于: http ://extensionoverflow.codeplex.com/
2008年11月11日XmlSerialize / XmlDeserialize现在已经实现并被unit testing 。
11.11.2008还有更多开发者的空间。 😉 立即join!
11.11.2008第三名贡献者join了ExtensionOverflow ,欢迎来到BKristensen
11.11.2008 FormatWith现在已经实现,并进行了unit testing 。
09.11.2008第二个贡献者join了ExtensionOverflow 。 欢迎来到chakrit 。
09.11.2008我们需要更多的开发者。 😉
09.11.2008 ThrowIfArgumentIsNull现已在Codeplex上实现并进行了unit testing 。
public static bool In<T>(this T source, params T[] list) { if(null==source) throw new ArgumentNullException("source"); return list.Contains(source); }
允许我replace:
if(reallyLongIntegerVariableName == 1 || reallyLongIntegerVariableName == 6 || reallyLongIntegerVariableName == 9 || reallyLongIntegerVariableName == 11) { // do something.... } and if(reallyLongStringVariableName == "string1" || reallyLongStringVariableName == "string2" || reallyLongStringVariableName == "string3") { // do something.... } and if(reallyLongMethodParameterName == SomeEnum.Value1 || reallyLongMethodParameterName == SomeEnum.Value2 || reallyLongMethodParameterName == SomeEnum.Value3 || reallyLongMethodParameterName == SomeEnum.Value4) { // do something.... }
附:
if(reallyLongIntegerVariableName.In(1,6,9,11)) { // do something.... } and if(reallyLongStringVariableName.In("string1","string2","string3")) { // do something.... } and if(reallyLongMethodParameterName.In(SomeEnum.Value1, SomeEnum.Value2, SomeEnum.Value3, SomeEnum.Value4) { // do something.... }
我在我的MiscUtil项目中有各种扩展方法(完整的源代码在那里 – 我不打算在这里重复)。 我的最爱,其中一些涉及其他类(如范围):
date和时间的东西 – 主要是unit testing。 不知道我会使用他们在生产:)
var birthday = 19.June(1976); var workingDay = 7.Hours() + 30.Minutes();
范围和步进 – 非常感谢Marc Gravell为他的操作员做的这些事情 :
var evenNaturals = 2.To(int.MaxValue).Step(2); var daysSinceBirth = birthday.To(DateTime.Today).Step(1.Days());
比较:
var myComparer = ProjectionComparer.Create(Person p => p.Name); var next = myComparer.ThenBy(p => p.Age); var reversed = myComparer.Reverse();
参数检查:
x.ThrowIfNull("x");
LINQ to XML应用于匿名types(或具有适当属性的其他types):
// <Name>Jon</Name><Age>32</Age> new { Name="Jon", Age=32}.ToXElements(); // Name="Jon" Age="32" (as XAttributes, obviously) new { Name="Jon", Age=32}.ToXAttributes()
推LINQ – 在这里解释需要很长的时间,但要search它。
string.Format快捷键:
public static class StringExtensions { // Enable quick and more natural string.Format calls public static string F(this string s, params object[] args) { return string.Format(s, args); } }
例:
var s = "The co-ordinate is ({0}, {1})".F(point.X, point.Y);
快速复制并粘贴到这里 。
难道你不觉得键入"some string".F("param")
而不是string.Format("some string", "param")
更自然吗?
要获得更具可读性的名称,请尝试以下其中一个build议:
s = "Hello {0} world {1}!".Fmt("Stack", "Overflow"); s = "Hello {0} world {1}!".FormatBy("Stack", "Overflow"); s = "Hello {0} world {1}!".FormatWith("Stack", "Overflow"); s = "Hello {0} world {1}!".Display("Stack", "Overflow"); s = "Hello {0} world {1}!".With("Stack", "Overflow");
..
这些有用吗?
public static bool CoinToss(this Random rng) { return rng.Next(2) == 0; } public static T OneOf<T>(this Random rng, params T[] things) { return things[rng.Next(things.Length)]; } Random rand; bool luckyDay = rand.CoinToss(); string babyName = rand.OneOf("John", "George", "Radio XBR74 ROCKS!");
public static class ComparableExtensions { public static bool Between<T>(this T actual, T lower, T upper) where T : IComparable<T> { return actual.CompareTo(lower) >= 0 && actual.CompareTo(upper) < 0; } }
例:
if (myNumber.Between(3,7)) { // .... }
扩展方法:
public static void AddRange<T, S>(this ICollection<T> list, params S[] values) where S : T { foreach (S value in values) list.Add(value); }
该方法适用于所有types,并允许您将一系列项目作为参数添加到列表中。
例:
var list = new List<Int32>(); list.AddRange(5, 4, 8, 4, 2);
通过一切手段把这个在codeplex项目。
序列化/反序列化对象到XML:
/// <summary>Serializes an object of type T in to an xml string</summary> /// <typeparam name="T">Any class type</typeparam> /// <param name="obj">Object to serialize</param> /// <returns>A string that represents Xml, empty otherwise</returns> public static string XmlSerialize<T>(this T obj) where T : class, new() { if (obj == null) throw new ArgumentNullException("obj"); var serializer = new XmlSerializer(typeof(T)); using (var writer = new StringWriter()) { serializer.Serialize(writer, obj); return writer.ToString(); } } /// <summary>Deserializes an xml string in to an object of Type T</summary> /// <typeparam name="T">Any class type</typeparam> /// <param name="xml">Xml as string to deserialize from</param> /// <returns>A new object of type T is successful, null if failed</returns> public static T XmlDeserialize<T>(this string xml) where T : class, new() { if (xml == null) throw new ArgumentNullException("xml"); var serializer = new XmlSerializer(typeof(T)); using (var reader = new StringReader(xml)) { try { return (T)serializer.Deserialize(reader); } catch { return null; } // Could not be deserialized to this type. } }
ForEach for IEnumerables
public static class FrameworkExtensions { // a map function public static void ForEach<T>(this IEnumerable<T> @enum, Action<T> mapFunction) { foreach (var item in @enum) mapFunction(item); } }
天真的例子:
var buttons = GetListOfButtons() as IEnumerable<Button>; // click all buttons buttons.ForEach(b => b.Click());
很酷的例子:
// no need to type the same assignment 3 times, just // new[] up an array and use foreach + lambda // everything is properly inferred by csc :-) new { itemA, itemB, itemC } .ForEach(item => { item.Number = 1; item.Str = "Hello World!"; });
注意:
这不像Select
因为Select
期望你的函数返回一些东西来转换成另一个列表。
ForEach只允许您为每个项目执行一些操作,而无需进行任何转换/数据操作。
我做了这个,所以我可以在一个更实用的风格编程,我很惊讶,List有一个ForEach,而IEnumerable没有。
把这个放在codeplex项目中
我的转换扩展程序允许您执行以下操作:
int i = myString.To<int>();
在TheSoftwareJedi.com上发布
public static T To<T>(this IConvertible obj) { return (T)Convert.ChangeType(obj, typeof(T)); } public static T ToOrDefault<T> (this IConvertible obj) { try { return To<T>(obj); } catch { return default(T); } } public static bool ToOrDefault<T> (this IConvertible obj, out T newObj) { try { newObj = To<T>(obj); return true; } catch { newObj = default(T); return false; } } public static T ToOrOther<T> (this IConvertible obj, T other) { try { return To<T>obj); } catch { return other; } } public static bool ToOrOther<T> (this IConvertible obj, out T newObj, T other) { try { newObj = To<T>(obj); return true; } catch { newObj = other; return false; } } public static T ToOrNull<T> (this IConvertible obj) where T : class { try { return To<T>(obj); } catch { return null; } } public static bool ToOrNull<T> (this IConvertible obj, out T newObj) where T : class { try { newObj = To<T>(obj); return true; } catch { newObj = null; return false; } }
你可以要求默认值(调用空构造函数或者数字“0”),指定一个“默认”值(我称之为“other”),或者请求null(T:class)。 我还提供了静默exception模型,以及一个典型的TryParse模型,它返回一个表示所采取行动的布尔值,并且一个外部参数保存新的值。 所以我们的代码可以做这样的事情
int i = myString.To<int>(); string a = myInt.ToOrDefault<string>(); //note type inference DateTime d = myString.ToOrOther(DateTime.MAX_VALUE); double d; //note type inference bool didItGiveDefault = myString.ToOrDefault(out d); string s = myDateTime.ToOrNull<string>();
我无法将Nullabletypes非常干净地整理成整个事物。 在我扔了毛巾之前,我尝试了大约20分钟。
我有一个loggingexception的扩展方法:
public static void Log(this Exception obj) { //your logging logic here }
它是这样使用的:
try { //Your stuff here } catch(Exception ex) { ex.Log(); }
[抱歉张贴两次; 第二个是更好的devise:-)]
public static class StringExtensions { /// <summary> /// Parses a string into an Enum /// </summary> /// <typeparam name="T">The type of the Enum</typeparam> /// <param name="value">String value to parse</param> /// <returns>The Enum corresponding to the stringExtensions</returns> public static T EnumParse<T>(this string value) { return StringExtensions.EnumParse<T>(value, false); } public static T EnumParse<T>(this string value, bool ignorecase) { if (value == null) { throw new ArgumentNullException("value"); } value = value.Trim(); if (value.Length == 0) { throw new ArgumentException("Must specify valid information for parsing in the string.", "value"); } Type t = typeof(T); if (!t.IsEnum) { throw new ArgumentException("Type provided must be an Enum.", "T"); } return (T)Enum.Parse(t, value, ignorecase); } }
用于将stringparsing为Enum。
public enum TestEnum { Bar, Test } public class Test { public void Test() { TestEnum foo = "Test".EnumParse<TestEnum>(); } }
信贷给斯科特·多曼
—编辑Codeplex项目—
我曾经问过Scott Dorman他是否会介意我们在Codeplex项目中发布他的代码。 这是我从他那里得到的答复:
感谢SOpost和CodePlex项目的单挑。 我已经提出了你的问题的答案。 是的,这些代码实际上是在CodeProject开放许可证( http://www.codeproject.com/info/cpol10.aspx )下的公共领域。
我对CodePlex项目中包含的这个问题没有任何问题,如果您想将我添加到项目中(用户名是sdorman),我将添加该方法以及其他一些枚举辅助方法。
我觉得这个很有用:
public static class PaulaBean { private static String paula = "Brillant"; public static String GetPaula<T>(this T obj) { return paula; } }
您可以在CodePlex上使用它。
DateTimeExtensions
例子:
DateTime firstDayOfMonth = DateTime.Now.First(); DateTime lastdayOfMonth = DateTime.Now.Last(); DateTime lastFridayInMonth = DateTime.Now.Last(DayOfWeek.Friday); DateTime nextFriday = DateTime.Now.Next(DayOfWeek.Friday); DateTime lunchTime = DateTime.Now.SetTime(11, 30); DateTime noonOnFriday = DateTime.Now.Next(DayOfWeek.Friday).Noon(); DateTime secondMondayOfMonth = DateTime.Now.First(DayOfWeek.Monday).Next(DayOfWeek.Monday).Midnight();
gitorious.org/cadenza是我见过的一些最有用的扩展方法的完整库。
这里是我经常使用的演示文稿格式。
public static string ToTitleCase(this string mText) { if (mText == null) return mText; System.Globalization.CultureInfo cultureInfo = System.Threading.Thread.CurrentThread.CurrentCulture; System.Globalization.TextInfo textInfo = cultureInfo.TextInfo; // TextInfo.ToTitleCase only operates on the string if is all lower case, otherwise it returns the string unchanged. return textInfo.ToTitleCase(mText.ToLower()); }
这是一个罗马数字的来回。 不经常使用,但可能会得心应手。 用法:
if ("IV".IsValidRomanNumeral()) { // Do useful stuff with the number 4. } Console.WriteLine("MMMDCCCLXXXVIII".ParseRomanNumeral()); Console.WriteLine(3888.ToRomanNumeralString());
来源:
public static class RomanNumeralExtensions { private const int NumberOfRomanNumeralMaps = 13; private static readonly Dictionary<string, int> romanNumerals = new Dictionary<string, int>(NumberOfRomanNumeralMaps) { { "M", 1000 }, { "CM", 900 }, { "D", 500 }, { "CD", 400 }, { "C", 100 }, { "XC", 90 }, { "L", 50 }, { "XL", 40 }, { "X", 10 }, { "IX", 9 }, { "V", 5 }, { "IV", 4 }, { "I", 1 } }; private static readonly Regex validRomanNumeral = new Regex( "^(?i:(?=[MDCLXVI])((M{0,3})((C[DM])|(D?C{0,3}))" + "?((X[LC])|(L?XX{0,2})|L)?((I[VX])|(V?(II{0,2}))|V)?))$", RegexOptions.Compiled); public static bool IsValidRomanNumeral(this string value) { return validRomanNumeral.IsMatch(value); } public static int ParseRomanNumeral(this string value) { if (value == null) { throw new ArgumentNullException("value"); } value = value.ToUpperInvariant().Trim(); var length = value.Length; if ((length == 0) || !value.IsValidRomanNumeral()) { throw new ArgumentException("Empty or invalid Roman numeral string.", "value"); } var total = 0; var i = length; while (i > 0) { var digit = romanNumerals[value[--i].ToString()]; if (i > 0) { var previousDigit = romanNumerals[value[i - 1].ToString()]; if (previousDigit < digit) { digit -= previousDigit; i--; } } total += digit; } return total; } public static string ToRomanNumeralString(this int value) { const int MinValue = 1; const int MaxValue = 3999; if ((value < MinValue) || (value > MaxValue)) { throw new ArgumentOutOfRangeException("value", value, "Argument out of Roman numeral range."); } const int MaxRomanNumeralLength = 15; var sb = new StringBuilder(MaxRomanNumeralLength); foreach (var pair in romanNumerals) { while (value / pair.Value > 0) { sb.Append(pair.Key); value -= pair.Value; } } return sb.ToString(); } }
处理尺寸的便捷方法:
public static class Extensions { public static int K(this int value) { return value * 1024; } public static int M(this int value) { return value * 1024 * 1024; } } public class Program { public void Main() { WSHttpContextBinding serviceMultipleTokenBinding = new WSHttpContextBinding() { MaxBufferPoolSize = 2.M(), // instead of 2097152 MaxReceivedMessageSize = 64.K(), // instead of 65536 }; } }
对于Winform控件:
/// <summary> /// Returns whether the function is being executed during design time in Visual Studio. /// </summary> public static bool IsDesignTime(this Control control) { if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) { return true; } if (control.Site != null && control.Site.DesignMode) { return true; } var parent = control.Parent; while (parent != null) { if (parent.Site != null && parent.Site.DesignMode) { return true; } parent = parent.Parent; } return false; } /// <summary> /// Sets the DropDownWidth to ensure that no item's text is cut off. /// </summary> public static void SetDropDownWidth(this ComboBox comboBox) { var g = comboBox.CreateGraphics(); var font = comboBox.Font; float maxWidth = 0; foreach (var item in comboBox.Items) { maxWidth = Math.Max(maxWidth, g.MeasureString(item.ToString(), font).Width); } if (comboBox.Items.Count > comboBox.MaxDropDownItems) { maxWidth += SystemInformation.VerticalScrollBarWidth; } comboBox.DropDownWidth = Math.Max(comboBox.Width, Convert.ToInt32(maxWidth)); }
IsDesignTime用法:
public class SomeForm : Form { public SomeForm() { InitializeComponent(); if (this.IsDesignTime()) { return; } // Do something that makes the visual studio crash or hang if we're in design time, // but any other time executes just fine } }
SetDropdownWidth用法:
ComboBox cbo = new ComboBox { Width = 50 }; cbo.Items.Add("Short"); cbo.Items.Add("A little longer"); cbo.Items.Add("Holy cow, this is a really, really long item. How in the world will it fit?"); cbo.SetDropDownWidth();
我忘了提及,在Codeplex上随意使用这些…
ThrowIfArgumentIsNull是一个很好的方法来做空检查我们都应该做的。
public static class Extensions { public static void ThrowIfArgumentIsNull<T>(this T obj, string parameterName) where T : class { if (obj == null) throw new ArgumentNullException(parameterName + " not allowed to be null"); } }
下面是使用它的方法,它可以用在你的名字空间的所有类上,或者你在其中使用名字空间的地方。
internal class Test { public Test(string input1) { input1.ThrowIfArgumentIsNull("input1"); } }
在CodePlex项目上使用这个代码是可以的。
移动到C#时,我错过了Visual Basic的With语句 ,所以在这里:
public static void With<T>(this T obj, Action<T> act) { act(obj); }
以下是如何在C#中使用它:
someVeryVeryLonggggVariableName.With(x => { x.Int = 123; x.Str = "Hello"; x.Str2 = " World!"; });
节省了很多打字!
比较这个:
someVeryVeryLonggggVariableName.Int = 123; someVeryVeryLonggggVariableName.Str = "Hello"; someVeryVeryLonggggVariableName.Str2 = " World!";
把codeplex项目
Takes a camelCaseWord or PascalCaseWord and "wordifies" it, ie camelCaseWord => camel Case Word
public static string Wordify( this string camelCaseWord ) { // if the word is all upper, just return it if( !Regex.IsMatch( camelCaseWord, "[az]" ) ) return camelCaseWord; return string.Join( " ", Regex.Split( camelCaseWord, @"(?<!^)(?=[AZ])" ) ); }
I often use it in conjuction with Capitalize
public static string Capitalize( this string word ) { return word[0].ToString( ).ToUpper( ) + word.Substring( 1 ); }
用法示例
SomeEntityObject entity = DataAccessObject.GetSomeEntityObject( id ); List<PropertyInfo> properties = entity.GetType().GetPublicNonCollectionProperties( ); // wordify the property names to act as column headers for an html table or something List<string> columns = properties.Select( p => p.Name.Capitalize( ).Wordify( ) ).ToList( );
Free to use in codeplex project
I found this one helpful
public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> pSeq) { return pSeq ?? Enumerable.Empty<T>(); }
It removes the null check in the calling code. You could now do
MyList.EmptyIfNull().Where(....)
Convert a double to string formatted using the specified culture:
public static class ExtensionMethods { public static string ToCurrency(this double value, string cultureName) { CultureInfo currentCulture = new CultureInfo(cultureName); return (string.Format(currentCulture, "{0:C}", value)); } }
例:
double test = 154.20; string testString = test.ToCurrency("en-US"); // $154.20
Below is an extension method that adapts Rick Strahl's code (and the comments too) to stop you having to guess or read the byte order mark of a byte array or text file each time you convert it to a string.
The snippet allows you to simply do:
byte[] buffer = File.ReadAllBytes(@"C:\file.txt"); string content = buffer.GetString();
If you find any bugs please add to the comments. Feel free to include it in the Codeplex project.
public static class Extensions { /// <summary> /// Converts a byte array to a string, using its byte order mark to convert it to the right encoding. /// Original article: http://www.west-wind.com/WebLog/posts/197245.aspx /// </summary> /// <param name="buffer">An array of bytes to convert</param> /// <returns>The byte as a string.</returns> public static string GetString(this byte[] buffer) { if (buffer == null || buffer.Length == 0) return ""; // Ansi as default Encoding encoding = Encoding.Default; /* EF BB BF UTF-8 FF FE UTF-16 little endian FE FF UTF-16 big endian FF FE 00 00 UTF-32, little endian 00 00 FE FF UTF-32, big-endian */ if (buffer[0] == 0xef && buffer[1] == 0xbb && buffer[2] == 0xbf) encoding = Encoding.UTF8; else if (buffer[0] == 0xfe && buffer[1] == 0xff) encoding = Encoding.Unicode; else if (buffer[0] == 0xfe && buffer[1] == 0xff) encoding = Encoding.BigEndianUnicode; // utf-16be else if (buffer[0] == 0 && buffer[1] == 0 && buffer[2] == 0xfe && buffer[3] == 0xff) encoding = Encoding.UTF32; else if (buffer[0] == 0x2b && buffer[1] == 0x2f && buffer[2] == 0x76) encoding = Encoding.UTF7; using (MemoryStream stream = new MemoryStream()) { stream.Write(buffer, 0, buffer.Length); stream.Seek(0, SeekOrigin.Begin); using (StreamReader reader = new StreamReader(stream, encoding)) { return reader.ReadToEnd(); } } } }
Here's one I just created today.
// requires .NET 4 public static TReturn NullOr<TIn, TReturn>(this TIn obj, Func<TIn, TReturn> func, TReturn elseValue = default(TReturn)) where TIn : class { return obj != null ? func(obj) : elseValue; } // versions for CLR 2, which doesn't support optional params public static TReturn NullOr<TIn, TReturn>(this TIn obj, Func<TIn, TReturn> func, TReturn elseValue) where TIn : class { return obj != null ? func(obj) : elseValue; } public static TReturn NullOr<TIn, TReturn>(this TIn obj, Func<TIn, TReturn> func) where TIn : class { return obj != null ? func(obj) : default(TReturn); }
It lets you do this:
var lname = thingy.NullOr(t => t.Name).NullOr(n => n.ToLower());
which is more fluent and (IMO) easier to read than this:
var lname = (thingy != null ? thingy.Name : null) != null ? thingy.Name.ToLower() : null;
"Please mark your answers with an acceptance to put the code in the Codeplex project."
为什么? All the Stuff on this site under CC-by-sa-2.5 , so just put your Extension overflow Project under the same license and you can freely use it.
Anyway, here is a String.Reverse function, based on this question .
/// <summary> /// Reverse a String /// </summary> /// <param name="input">The string to Reverse</param> /// <returns>The reversed String</returns> public static string Reverse(this string input) { char[] array = input.ToCharArray(); Array.Reverse(array); return new string(array); }
I got tired of tedious null-checking while pulling values from MySqlDataReader, so:
public static DateTime? GetNullableDateTime(this MySqlDataReader dr, string fieldName) { DateTime? nullDate = null; return dr.IsDBNull(dr.GetOrdinal(fieldName)) ? nullDate : dr.GetDateTime(fieldName); } public static string GetNullableString(this MySqlDataReader dr, string fieldName) { return dr.IsDBNull(dr.GetOrdinal(fieldName)) ? String.Empty : dr.GetString(fieldName); } public static char? GetNullableChar(this MySqlDataReader dr, string fieldName) { char? nullChar = null; return dr.IsDBNull(dr.GetOrdinal(fieldName)) ? nullChar : dr.GetChar(fieldName); }
Of course this could be used with any SqlDataReader.
Both hangy and Joe had some good comments on how to do this, and I have since had an opportunity to implement something similar in a different context, so here is another version:
public static int? GetNullableInt32(this IDataRecord dr, int ordinal) { int? nullInt = null; return dr.IsDBNull(ordinal) ? nullInt : dr.GetInt32(ordinal); } public static int? GetNullableInt32(this IDataRecord dr, string fieldname) { int ordinal = dr.GetOrdinal(fieldname); return dr.GetNullableInt32(ordinal); } public static bool? GetNullableBoolean(this IDataRecord dr, int ordinal) { bool? nullBool = null; return dr.IsDBNull(ordinal) ? nullBool : dr.GetBoolean(ordinal); } public static bool? GetNullableBoolean(this IDataRecord dr, string fieldname) { int ordinal = dr.GetOrdinal(fieldname); return dr.GetNullableBoolean(ordinal); }
It irritated me that LINQ gives me an OrderBy that takes a class implementing IComparer as an argument, but does not support passing in a simple anonymous comparer function. I rectified that.
This class creates an IComparer from your comparer function…
/// <summary> /// Creates an <see cref="IComparer{T}"/> instance for the given /// delegate function. /// </summary> internal class ComparerFactory<T> : IComparer<T> { public static IComparer<T> Create(Func<T, T, int> comparison) { return new ComparerFactory<T>(comparison); } private readonly Func<T, T, int> _comparison; private ComparerFactory(Func<T, T, int> comparison) { _comparison = comparison; } #region IComparer<T> Members public int Compare(T x, T y) { return _comparison(x, y); } #endregion }
…and these extension methods expose my new OrderBy overloads on enumerables. I doubt this works for LINQ to SQL, but it's great for LINQ to Objects.
public static class EnumerableExtensions { /// <summary> /// Sorts the elements of a sequence in ascending order by using a specified comparison delegate. /// </summary> public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, TKey, int> comparison) { var comparer = ComparerFactory<TKey>.Create(comparison); return source.OrderBy(keySelector, comparer); } /// <summary> /// Sorts the elements of a sequence in descending order by using a specified comparison delegate. /// </summary> public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, TKey, int> comparison) { var comparer = ComparerFactory<TKey>.Create(comparison); return source.OrderByDescending(keySelector, comparer); } }
You're welcome to put this on codeplex if you like.
This one is for MVC it adds the ability to generate a <label />
tag to the Html
variable that is available in every ViewPage
. Hopefully it will be of use to others trying to develop similar extensions.
使用:
<%= Html.Label("LabelId", "ForId", "Text")%>
输出:
<label id="LabelId" for="ForId">Text</label>
码:
public static class HtmlHelperExtensions { public static string Label(this HtmlHelper Html, string @for, string text) { return Html.Label(null, @for, text); } public static string Label(this HtmlHelper Html, string @for, string text, object htmlAttributes) { return Html.Label(null, @for, text, htmlAttributes); } public static string Label(this HtmlHelper Html, string @for, string text, IDictionary<string, object> htmlAttributes) { return Html.Label(null, @for, text, htmlAttributes); } public static string Label(this HtmlHelper Html, string id, string @for, string text) { return Html.Label(id, @for, text, null); } public static string Label(this HtmlHelper Html, string id, string @for, string text, object htmlAttributes) { return Html.Label(id, @for, text, new RouteValueDictionary(htmlAttributes)); } public static string Label(this HtmlHelper Html, string id, string @for, string text, IDictionary<string, object> htmlAttributes) { TagBuilder tag = new TagBuilder("label"); tag.MergeAttributes(htmlAttributes); if (!string.IsNullOrEmpty(id)) tag.MergeAttribute("id", Html.AttributeEncode(id)); tag.MergeAttribute("for", Html.AttributeEncode(@for)); tag.SetInnerText(Html.Encode(text)); return tag.ToString(TagRenderMode.Normal); } }
Turn this:
DbCommand command = connection.CreateCommand(); command.CommandText = "SELECT @param"; DbParameter param = command.CreateParameter(); param.ParameterName = "@param"; param.Value = "Hello World"; command.Parameters.Add(param);
… into this:
DbCommand command = connection.CreateCommand("SELECT {0}", "Hello World");
… using this extension method:
using System; using System.Data.Common; using System.Globalization; using System.Reflection; namespace DbExtensions { public static class Db { static readonly Func<DbConnection, DbProviderFactory> getDbProviderFactory; static readonly Func<DbCommandBuilder, int, string> getParameterName; static readonly Func<DbCommandBuilder, int, string> getParameterPlaceholder; static Db() { getDbProviderFactory = (Func<DbConnection, DbProviderFactory>)Delegate.CreateDelegate(typeof(Func<DbConnection, DbProviderFactory>), typeof(DbConnection).GetProperty("DbProviderFactory", BindingFlags.Instance | BindingFlags.NonPublic).GetGetMethod(true)); getParameterName = (Func<DbCommandBuilder, int, string>)Delegate.CreateDelegate(typeof(Func<DbCommandBuilder, int, string>), typeof(DbCommandBuilder).GetMethod("GetParameterName", BindingFlags.Instance | BindingFlags.NonPublic, Type.DefaultBinder, new Type[] { typeof(Int32) }, null)); getParameterPlaceholder = (Func<DbCommandBuilder, int, string>)Delegate.CreateDelegate(typeof(Func<DbCommandBuilder, int, string>), typeof(DbCommandBuilder).GetMethod("GetParameterPlaceholder", BindingFlags.Instance | BindingFlags.NonPublic, Type.DefaultBinder, new Type[] { typeof(Int32) }, null)); } public static DbProviderFactory GetProviderFactory(this DbConnection connection) { return getDbProviderFactory(connection); } public static DbCommand CreateCommand(this DbConnection connection, string commandText, params object[] parameters) { if (connection == null) throw new ArgumentNullException("connection"); return CreateCommandImpl(GetProviderFactory(connection).CreateCommandBuilder(), connection.CreateCommand(), commandText, parameters); } private static DbCommand CreateCommandImpl(DbCommandBuilder commandBuilder, DbCommand command, string commandText, params object[] parameters) { if (commandBuilder == null) throw new ArgumentNullException("commandBuilder"); if (command == null) throw new ArgumentNullException("command"); if (commandText == null) throw new ArgumentNullException("commandText"); if (parameters == null || parameters.Length == 0) { command.CommandText = commandText; return command; } object[] paramPlaceholders = new object[parameters.Length]; for (int i = 0; i < paramPlaceholders.Length; i++) { DbParameter dbParam = command.CreateParameter(); dbParam.ParameterName = getParameterName(commandBuilder, i); dbParam.Value = parameters[i] ?? DBNull.Value; command.Parameters.Add(dbParam); paramPlaceholders[i] = getParameterPlaceholder(commandBuilder, i); } command.CommandText = String.Format(CultureInfo.InvariantCulture, commandText, paramPlaceholders); return command; } } }
More ADO.NET extension methods: DbExtensions