让我们把你的优秀和最喜欢的扩展方法列一个列表。

要求是必须发布完整的代码,以及如何使用它的示例和解释。

基于对这个主题的高度兴趣,我在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上实现和单元测试。


当前回答

您可能已经知道扩展方法的一个有趣用法是作为一种mixin。一些扩展方法,比如XmlSerializable,几乎污染了所有类;这对大多数人来说没有意义,比如Thread和SqlConnection。

一些功能应该显式地混合到希望拥有它的类中。我对这种类型提出了一种新的表示法,以M为前缀。

XmlSerializable是这样的:

public interface MXmlSerializable { }
public static class XmlSerializable {
  public static string ToXml(this MXmlSerializable self) {
    if (self == null) throw new ArgumentNullException();
    var serializer = new XmlSerializer(self.GetType());
    using (var writer = new StringWriter()) {
      serializer.Serialize(writer, self);
      return writer.GetStringBuilder().ToString();
    }
  }
  public static T FromXml<T>(string xml) where T : MXmlSerializable {
    var serializer = new XmlSerializer(typeof(T));
    return (T)serializer.Deserialize(new StringReader(xml));
  }
}

然后一个类将其混合:

public class Customer : MXmlSerializable {
  public string Name { get; set; }
  public bool Preferred { get; set; }
}

用法很简单:

var customer = new Customer { 
  Name = "Guybrush Threepwood", 
  Preferred = true };
var xml = customer.ToXml();

如果您喜欢这个想法,您可以在项目中为有用的mixin创建一个新的名称空间。你怎么看?

哦,顺便说一下,我认为大多数扩展方法都应该显式地测试null。

其他回答

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"。

这一个是MVC,它添加了生成一个<label />标签到Html变量的能力,在每个ViewPage中可用。希望它能对其他试图开发类似扩展的人有所帮助。

Use:

<%= 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);
    }
}

我喜欢这些NUnit Assert扩展:http://svn.caffeine-it.com/openrasta/trunk/src/Rasta.Testing/AssertExtensions.cs

如果你需要检查字符串的Is All char为0:

 static public bool   IsAllZero            (this string input)
        {
            if(string.IsNullOrEmpty(input))
                return true;
            foreach (char ch in input)
            {
                if(ch != '0')
                    return false;
            }
            return true;
        }

一些DataSet/DataRow扩展,使使用db结果更简单

只需在DataRow上使用. field ("fieldname"),如果可以,它将强制转换它,可选的默认值可以包括在内。

还有DataSet上的. hasrows(),这样你就不需要检查表和行的存在。

例子:

using (DataSet ds = yourcall()) 
{
  if (ds.HasRows())
  {
     foreach (DataRow dr in ds.Tables[0].Rows)
     {
        int id = dr.Field<int>("ID");
        string name = dr.Field<string>("Name");
        string Action = dr.Field<string>("Action", "N/A");
     }
  }
}

代码:

using System;
using System.Data;

public static class DataSetExtensions
{
    public static T Field<T>(this DataRow row, string columnName, T defaultValue)
    {
        try
        {
            return row.Field<T>(columnName);
        }
        catch
        {
            return defaultValue;
        }
    }

    public static T Field<T>(this DataRow row, string columnName)
    {
        if (row[columnName] == null)
            throw new NullReferenceException(columnName + " does not exist in DataRow");

        string value = row[columnName].ToString();

        if (typeof(T) == "".GetType())
        {
            return (T)Convert.ChangeType(value, typeof(T));
        }
        else if (typeof(T) == 0.GetType())
        {
            return (T)Convert.ChangeType(int.Parse(value), typeof(T));
        }
        else if (typeof(T) == false.GetType())
        {
            return (T)Convert.ChangeType(bool.Parse(value), typeof(T));
        }
        else if (typeof(T) == DateTime.Now.GetType())
        {
            return (T)Convert.ChangeType(DateTime.Parse(value), typeof(T));
        }
        else if (typeof(T) == new byte().GetType())
        {
            return (T)Convert.ChangeType(byte.Parse(value), typeof(T));
        }
        else if (typeof(T) == new float().GetType())
        {
            return (T)Convert.ChangeType(float.Parse(value), typeof(T));
        }
        else
        {
            throw new ArgumentException(string.Format("Cannot cast '{0}' to '{1}'.", value, typeof(T).ToString()));
        }
    }

    public static bool HasRows(this DataSet dataSet) 
    {
        return (dataSet.Tables.Count > 0 && dataSet.Tables[0].Rows.Count > 0);
    }
}