让我们把你的优秀和最喜欢的扩展方法列一个列表。
要求是必须发布完整的代码,以及如何使用它的示例和解释。
基于对这个主题的高度兴趣,我在Codeplex上建立了一个名为extensionoverflow的开源项目。
请将您的回答标记为接受,以便将代码放入Codeplex项目。
请张贴完整的源代码,而不是一个链接。
Codeplex上新闻:
24.08.2010 Codeplex页面现在在这里:http://extensionoverflow.codeplex.com/
11.11.2008 XmlSerialize / XmlDeserialize现在是实现和单元测试。
11.11.2008仍有发展空间。;-)现在就加入!
11.11.2008第三位贡献者加入了ExtensionOverflow,欢迎加入BKristensen
11.11.2008 FormatWith现在是实现和单元测试。
09.11.2008第二个贡献者加入ExtensionOverflow。欢迎来到chakrit。
我们需要更多的开发人员。: -)
09.11.2008 ThrowIfArgumentIsNull现已在Codeplex上实现和单元测试。
这个还没有完全烤熟因为我们今天早上才想到。它将为Type生成一个完整的类定义。当您有一个大型类,想要创建一个子集或完整定义,但无法访问它的情况下非常有用。例如,将对象存储在数据库中等等。
public static class TypeExtensions
{
public static string GenerateClassDefinition(this Type type)
{
var properties = type.GetFields();
var sb = new StringBuilder();
var classtext = @"private class $name
{
$props}";
foreach (var p in GetTypeInfo(type))
{
sb.AppendFormat(" public {0} {1} ", p.Item2, p.Item1).AppendLine(" { get; set; }");
}
return classtext.Replace("$name", type.Name).Replace("$props", sb.ToString());
}
#region Private Methods
private static List<Tuple<string, string>> GetTypeInfo(Type type)
{
var ret = new List<Tuple<string, string>>();
var fields = type.GetFields();
var props = type.GetProperties();
foreach(var p in props) ret.Add(new Tuple<string, string>(p.Name, TranslateType(p.PropertyType)));
foreach(var f in fields) ret.Add(new Tuple<string, string>(f.Name, TranslateType(f.FieldType)));
return ret;
}
private static string TranslateType(Type input)
{
string ret;
if (Nullable.GetUnderlyingType(input) != null)
{
ret = string.Format("{0}?", TranslateType(Nullable.GetUnderlyingType(input)));
}
else
{
switch (input.Name)
{
case "Int32": ret = "int"; break;
case "Int64": ret = "long"; break;
case "IntPtr": ret = "long"; break;
case "Boolean": ret = "bool"; break;
case "String":
case "Char":
case "Decimal":
ret = input.Name.ToLower(); break;
default: ret = input.Name; break;
}
}
return ret;
}
#endregion
}
使用示例:
Process.GetProcesses().First().GetType().GenerateClassDefinition();
如果使用linqpad,变得更加方便:
Process.GetProcesses().First().GetType().GenerateClassDefinition().Dump();
HTH。这些是我的一些主要问题。
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
namespace Insert.Your.Namespace.Here.Helpers
{
public static class Extensions
{
public static bool IsNullOrEmpty<T>(this IEnumerable<T> iEnumerable)
{
// Cheers to Joel Mueller for the bugfix. Was .Count(), now it's .Any()
return iEnumerable == null ||
!iEnumerable.Any();
}
public static IList<T> ToListIfNotNullOrEmpty<T>(this IList<T> iList)
{
return iList.IsNullOrEmpty() ? null : iList;
}
public static PagedList<T> ToPagedListIfNotNullOrEmpty<T>(this PagedList<T> pagedList)
{
return pagedList.IsNullOrEmpty() ? null : pagedList;
}
public static string ToPluralString(this int value)
{
return value == 1 ? string.Empty : "s";
}
public static string ToReadableTime(this DateTime value)
{
TimeSpan span = DateTime.Now.Subtract(value);
const string plural = "s";
if (span.Days > 7)
{
return value.ToShortDateString();
}
switch (span.Days)
{
case 0:
switch (span.Hours)
{
case 0:
if (span.Minutes == 0)
{
return span.Seconds <= 0
? "now"
: string.Format("{0} second{1} ago",
span.Seconds,
span.Seconds != 1 ? plural : string.Empty);
}
return string.Format("{0} minute{1} ago",
span.Minutes,
span.Minutes != 1 ? plural : string.Empty);
default:
return string.Format("{0} hour{1} ago",
span.Hours,
span.Hours != 1 ? plural : string.Empty);
}
default:
return string.Format("{0} day{1} ago",
span.Days,
span.Days != 1 ? plural : string.Empty);
}
}
public static string ToShortGuidString(this Guid value)
{
return Convert.ToBase64String(value.ToByteArray())
.Replace("/", "_")
.Replace("+", "-")
.Substring(0, 22);
}
public static Guid FromShortGuidString(this string value)
{
return new Guid(Convert.FromBase64String(value.Replace("_", "/")
.Replace("-", "+") + "=="));
}
public static string ToStringMaximumLength(this string value, int maximumLength)
{
return ToStringMaximumLength(value, maximumLength, "...");
}
public static string ToStringMaximumLength(this string value, int maximumLength, string postFixText)
{
if (string.IsNullOrEmpty(postFixText))
{
throw new ArgumentNullException("postFixText");
}
return value.Length > maximumLength
? string.Format(CultureInfo.InvariantCulture,
"{0}{1}",
value.Substring(0, maximumLength - postFixText.Length),
postFixText)
:
value;
}
public static string SlugDecode(this string value)
{
return value.Replace("_", " ");
}
public static string SlugEncode(this string value)
{
return value.Replace(" ", "_");
}
}
}
我创建了一个漂亮的Each扩展,具有与jQuery的Each函数相同的行为。
它允许如下所示,你可以获得当前值的索引,并通过返回false跳出循环:
new[] { "first", "second", "third" }.Each((value, index) =>
{
if (value.Contains("d"))
return false;
Console.Write(value);
return true;
});
下面是代码
/// <summary>
/// Generic iterator function that is useful to replace a foreach loop with at your discretion. A provided action is performed on each element.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="action">Function that takes in the current value in the sequence.
/// <returns></returns>
public static IEnumerable<T> Each<T>(this IEnumerable<T> source, Action<T> action)
{
return source.Each((value, index) =>
{
action(value);
return true;
});
}
/// <summary>
/// Generic iterator function that is useful to replace a foreach loop with at your discretion. A provided action is performed on each element.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="action">Function that takes in the current value and its index in the sequence.
/// <returns></returns>
public static IEnumerable<T> Each<T>(this IEnumerable<T> source, Action<T, int> action)
{
return source.Each((value, index) =>
{
action(value, index);
return true;
});
}
/// <summary>
/// Generic iterator function that is useful to replace a foreach loop with at your discretion. A provided action is performed on each element.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="action">Function that takes in the current value in the sequence. Returns a value indicating whether the iteration should continue. So return false if you don't want to iterate anymore.</param>
/// <returns></returns>
public static IEnumerable<T> Each<T>(this IEnumerable<T> source, Func<T, bool> action)
{
return source.Each((value, index) =>
{
return action(value);
});
}
/// <summary>
/// Generic iterator function that is useful to replace a foreach loop with at your discretion. A provided action is performed on each element.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="action">Function that takes in the current value and its index in the sequence. Returns a value indicating whether the iteration should continue. So return false if you don't want to iterate anymore.</param>
/// <returns></returns>
public static IEnumerable<T> Each<T>(this IEnumerable<T> source, Func<T, int, bool> action)
{
if (source == null)
return source;
int index = 0;
foreach (var sourceItem in source)
{
if (!action(sourceItem, index))
break;
index++;
}
return source;
}
python字典方法:
/// <summary>
/// If a key exists in a dictionary, return its value,
/// otherwise return the default value for that type.
/// </summary>
public static U GetWithDefault<T, U>(this Dictionary<T, U> dict, T key)
{
return dict.GetWithDefault(key, default(U));
}
/// <summary>
/// If a key exists in a dictionary, return its value,
/// otherwise return the provided default value.
/// </summary>
public static U GetWithDefault<T, U>(this Dictionary<T, U> dict, T key, U defaultValue)
{
return dict.ContainsKey(key)
? dict[key]
: defaultValue;
}
当您希望将时间戳附加到文件名以确保唯一性时非常有用。
/// <summary>
/// Format a DateTime as a string that contains no characters
//// that are banned from filenames, such as ':'.
/// </summary>
/// <returns>YYYY-MM-DD_HH.MM.SS</returns>
public static string ToFilenameString(this DateTime dt)
{
return dt.ToString("s").Replace(":", ".").Replace('T', '_');
}
在单元测试中很有用:
public static IList<T> Clone<T>(this IList<T> list) where T : ICloneable
{
var ret = new List<T>(list.Count);
foreach (var item in list)
ret.Add((T)item.Clone());
// done
return ret;
}
像TWith2Sugars这样的一系列,交替缩短语法:
public static long? ToNullableInt64(this string val)
{
long ret;
return Int64.TryParse(val, out ret) ? ret : new long?();
}
最后,在BCL中是否已经有一些东西做了下面的事情?
public static void Split<T>(this T[] array,
Func<T,bool> determinator,
IList<T> onTrue,
IList<T> onFalse)
{
if (onTrue == null)
onTrue = new List<T>();
else
onTrue.Clear();
if (onFalse == null)
onFalse = new List<T>();
else
onFalse.Clear();
if (determinator == null)
return;
foreach (var item in array)
{
if (determinator(item))
onTrue.Add(item);
else
onFalse.Add(item);
}
}
static string Format( this string str,
, params Expression<Func<string,object>>[] args)
{
var parameters = args.ToDictionary
( e=>string.Format("{{{0}}}",e.Parameters[0].Name)
, e=>e.Compile()(e.Parameters[0].Name));
var sb = new StringBuilder(str);
foreach(var kv in parameters)
{
sb.Replace( kv.Key
, kv.Value != null ? kv.Value.ToString() : "");
}
return sb.ToString();
}
有了上面的扩展,你可以这样写:
var str = "{foo} {bar} {baz}".Format(foo=>foo, bar=>2, baz=>new object());
你会得到"foo 2 System.Object"。