Quais são seus métodos de extensão favoritos para C #? (codeplex.com/extensionoverflow)


478

Vamos fazer uma lista de respostas onde você publica seus métodos de extensão excelentes e favoritos .

O requisito é que o código completo seja publicado e um exemplo e uma explicação sobre como usá-lo.

Com base no grande interesse neste tópico, configurei um projeto de código aberto chamado extensionoverflow no Codeplex .

Marque suas respostas com uma aceitação para inserir o código no projeto Codeplex.

Poste o código fonte completo e não um link.

Notícias Codeplex:

24.08.2010 A página Codeplex agora está aqui: http://extensionoverflow.codeplex.com/

11.11.2008 XmlSerialize / XmlDeserialize agora está implementado e testado por unidade .

11.11.2008 Ainda há espaço para mais desenvolvedores. ;-) Inscreva-se agora!

11.11.2008 Terceiro colaborador ingressou no ExtensionOverflow , bem-vindo ao BKristensen

11.11.2008 FormatWith agora está implementado e testado por unidade .

09.11.2008 O segundo colaborador ingressou no ExtensionOverflow . bem-vindo ao chakrit .

09.11.2008 Precisamos de mais desenvolvedores. ;-)

09.11.2008 ThrowIfArgumentIsNull agora implementado e testado por unidade no Codeplex.


Agora o primeiro código está confirmado no site Codeplex.
bovium 7/11/08

Infelizmente, Erik tudo começou agora no codeplex. Por favor, junte-se de qualquer maneira.
bovium 11/11/08

3
Parece muito bom. Eu tenho um comentário sobre como nomear as classes estáticas. Nomear as extensões <type> não é muito informativo. Por exemplo, StringExtensions contém itens de formatação e xml. Eu acho que é melhor nomear a classe com o motivo de você estender esse tipo. Por exemplo, UnixDateTimeConversions. Você pode razoavelmente adivinhar que ele possui métodos para converter de e para o tempo Unix. Apenas um pensamento!
ecoffey

Marque esta URL para saber mais sobre C Métodos # Extensão planetofcoders.com/c-extension-methods
Gaurav Agrawal

Respostas:


232
public static bool In<T>(this T source, params T[] list)
{
  if(null==source) throw new ArgumentNullException("source");
  return list.Contains(source);
}

Permite substituir:

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....
}

Com:

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....
}

2
Bem, ele compila se você estiver usando System.Linq;
Ryu

11
Talvez "EqualsAnyOf" seja um nome melhor que "In"?
21810 Tom Bushell

10
Não sei se gosto - gosto da brevidade In, mas talvez IsInseja melhor.
Winston Smith

50
Usando o mesmo método Contains: (new [] {1, 2, 3}). Contém (a)
Max Toro

4
Pensei In<T>(...)também e achei o método de extensão mais útil fora da biblioteca padrão. Mas estou em desacordo com o nome In. Um nome de método deve estar descrevendo o que faz, mas Innão o faz. Eu chamei IsAnyOf<T>(...), mas acho IsIn<T>(...)que seria adequado também.
JBSnorro

160

Eu tenho vários métodos de extensão no meu projeto MiscUtil (a fonte completa está disponível lá - não vou repeti-lo aqui). Meus favoritos, alguns dos quais envolvem outras classes (como intervalos):

Data e hora - principalmente para testes de unidade. Não tenho certeza se os usaria na produção :)

var birthday = 19.June(1976);
var workingDay = 7.Hours() + 30.Minutes();

Intervalos e passos - um enorme agradecimento a Marc Gravell pelo material do operador para tornar isso possível:

var evenNaturals = 2.To(int.MaxValue).Step(2);
var daysSinceBirth = birthday.To(DateTime.Today).Step(1.Days());

Comparações:

var myComparer = ProjectionComparer.Create(Person p => p.Name);
var next = myComparer.ThenBy(p => p.Age);
var reversed = myComparer.Reverse();

Verificação de argumento:

x.ThrowIfNull("x");

LINQ to XML aplicado a tipos anônimos (ou outros tipos com propriedades apropriadas):

// <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()

Pressione LINQ - levaria muito tempo para explicar aqui, mas procure-o.


1
Isso é bom! Você deve colocá-lo no Google Code ou CodePlex para que eu possa lhe enviar algumas manchas :-) eu prometo que vai ser :-P legível
chakrit

3
@ Bovium: Você já pode ver o código. Siga o link na primeira frase - a fonte completa está lá.
Jon Skeet

1
@bovium: Prefiro fazer isso sozinho, colocando no code.google.com e gerenciando o projeto, se você não se importa. Obviamente, você está dentro da licença para colocá-lo no CodePlex, se você manter a atribuição apropriada, mas eu prefiro classificar a mim em breve, a menos que você está desesperado :)
Jon Skeet

1
@Jon Skeet. É colocado sob a licença MIT livre de uso para todos. Comercialmente ou de código aberto. Por que não unir forças e criar uma biblioteca de métodos de extensão para o público?
bovium 8/08

1
Só porque eu faço muitos outros pedaços nessa biblioteca. Você pode tirar uma cópia de tudo isso para o seu projeto, mas prefiro manter uma cópia no meu próprio projeto.
Jon Skeet

147

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

Exemplo:

var s = "The co-ordinate is ({0}, {1})".F(point.X, point.Y);

Para copiar e colar rapidamente, clique aqui .

Você não acha mais natural digitar em "some string".F("param")vez de string.Format("some string", "param")?

Para um nome mais legível , tente uma destas sugestões:

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");

..


11
Certamente é curto - mas será ilegível para qualquer novo membro da sua equipe.
Jon Skeet

3
Acho que a legibilidade é mais importante no esquema mais amplo do seu código do que algumas declarações abreviadas que podem ser rapidamente pesquisadas / solicitadas.
chakrit

6
Pessoalmente, eu gostaria de um objeto Formatador separado, que o BCL pudesse analisar o padrão de uma vez e reutilizá-lo. Isso aumentaria a legibilidade e o desempenho. Eu pedi a equipe BCL - vamos ver ...
Jon Skeet

3
É um método de extensão, é claro que será ilegível para os novos membros da equipe. Eu pensei que era essa a idéia com essas coisas espirituosas? De que outra forma os novos membros saberão quão inteligentes somos?
MarkJ

17
Ok ... Eu apenas coloquei isso em ação e segui com. Com - para que você obtenha "Este é um {0}". Com ("teste"), é muito legível e faz sentido. FYI
klkitchens 04/03/09

89

Estes são de alguma utilidade?

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!");

isso imita a função pythons random.choice (seq). agradável.
Daren Thomas

6
Algumas coisas: eu recomendo que OneOfaceite qualquer IList<T> . Então você sempre pode também ter uma sobrecarga que recebe um paramsargumento e apenas passa isso para a IList<T>sobrecarga. Eu dei uma resposta (bem na parte inferior agora) com um NextBoolmétodo semelhante ao seu CoinToss, mas com uma sobrecarga que requer um probabilityparâmetro (e se eu quiser que algo aconteça 75% do tempo?). Além disso, apenas uma escolha de nit: o seu código de exemplo emitirá um NullReferenceExceptiondado que randnunca é inicializado.
Dan Tao

3
+1 Eu realmente gosto disso, mas prefiro CoinTossser implementado rng.NextDouble() < .5porque .Next(int)é feito internamente com, .NextDouble()para que você salve um elenco, um * e um cheque.
Lasse Espeholt 30/09/10

76
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;
  }
}

Exemplo:

if (myNumber.Between(3,7))
{
  // ....
}

19
Eu amo esse, mas estou tentando decidir se é certo fazer os limites verificarem inclusive o valor mínimo, mas exclusivo no valor máximo. Eu me pergunto se isso seria confuso. 5.Entre (5,10) é verdadeiro, mas 5.Entre (1,5) é falso. Nem tenho certeza de que um método Within complementar ajudaria. Thougts?
9788 Steve Hiner #

12
O nome "IsBetween" não faria mais sentido? Talvez também faça um IsBetweenInclusive e IsBetweenExclusive. No entanto, não faço ideia de qual delas tomar por padrão.
fretje

2
@ Steve: faz mais sentido se fosse uma extensão de data e hora.
Joel Coehoorn

16
Para mim, entre implica: 5.Between (5,10) retorna false e 10.Between (5,10) retorna false também. Isso me parece natural.
Alex Baranosky

3
Parece-me que várias pessoas têm idéias diferentes sobre o que é natural. Por isso, provavelmente deve ser explicitamente declarado o que está sendo usado (por exemplo, inclusivo versus exclusivo), pois isso pode ser uma fonte muito fácil de erros.
1013 David Miani

58

O método de extensão:

public static void AddRange<T, S>(this ICollection<T> list, params S[] values)
    where S : T
{
    foreach (S value in values)
        list.Add(value);
}

O método se aplica a todos os tipos e permite adicionar um intervalo de itens a uma lista como parâmetros.

Exemplo:

var list = new List<Int32>();
list.AddRange(5, 4, 8, 4, 2);

15
Seria melhor como este IList <T>

21
Basta usar o inicializador de coleção =>var list = new List<int>{5,4,8,4,2};
Arnis Lapsa

Por que não apenas chamar List <T> .AddRange (coleção IEnumerable <T>) dentro do seu método?
Rauhotz 13/03/10

8
@ Will: Na verdade, seria melhor aceitar um ICollection<T>; também poderia ser usado em, por exemplo, LinkedList<T>e HashSet<T>não apenas em coleções indexadas.
Dan Tao

2
Editado para permitir a covariância em pre-.net 4.0
BlueRaja - Danny Pflughoeft

55

Por todos os meios, coloque isso no projeto codeplex.

Serializando / desserializando objetos para 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.
    }
}

8
Eu estaria tentado a chamar o primeiro ToXml()(como ToString())
Jay Bazuzi

1
Desculpas ao OP se ele intencionalmente o escreveu dessa maneira, mas o uso de MemoryStreams AND XmlReader / XmlWriter foi um exagero. A classe StringReader e StringWriter são perfeitas para esta operação.
Portman

2
Cuidado, isso não é seguro para threads. Você definitivamente deve sincronizar seu acesso ao dicionário de serialisadores estáticos.
Yann Schwartz

2
@ Yann, @ T, É muito mais fácil se você apenas adicionar o atributo "estático do thread". Em seguida, um novo cache será criado por thread. Não há necessidade de sincronização.
22830 Frank Krueger

1
@ Jonathan C Dickinson: Parece que o MSDN documenta aqui msdn.microsoft.com/en-us/library/… que o construtor usado (novo XmlSerializer (tipo)) não tem um problema de vazamento de memória. Talvez o código de cache não seja necessário?
Slolife 26/08/10

46

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

Exemplo ingênuo:

var buttons = GetListOfButtons() as IEnumerable<Button>;

// click all buttons
buttons.ForEach(b => b.Click());

Exemplo legal:

// 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!";
    });

Nota:

Não é assim, Selectporque Select espera que sua função retorne algo como para se transformar em outra lista.

O ForEach simplesmente permite que você execute algo para cada um dos itens sem nenhuma transformação / manipulação de dados.

Fiz isso para que eu possa programar em um estilo mais funcional e fiquei surpreso que o List tenha um ForEach, enquanto o IEnumerable não.

Coloque isso no projeto codeplex


13
Postar no porque IEnumerable de LINQ <T> extensões não incluem um foreach: stackoverflow.com/questions/317874/...
Neil

13
Eu recomendo ler isso antes de usar o método: blogs.msdn.com/ericlippert/archive/2009/05/18/…
jpbochi

2
@jpbochi: Este é apenas demagogia Microsoft
abatishchev

1
@abatishchev E seu comentário é apenas preconceito contra a Microsoft. Não invalida qualquer palavra escrita por Eric. Os argumentos de alguém não são válidos ou inválidos apenas por causa da empresa em que trabalha.
jpbochi

1
A propósito, deixe-me esclarecer um ponto. Eu não disse que você não deveria usar esse método de extensão ForEach. Eu apenas disse que você deveria considerar os pontos que Eric expôs antes de decidir se deve usá-lo ou não. Eu li e decidi não usá-lo. Você é livre para fazer o que quiser com seu código.
jpbochi

43

Minhas extensões de conversão que permitem:

int i = myString.To<int>();

Aqui está, conforme publicado em 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;
    }
}

Você pode solicitar o padrão (chama o construtor em branco ou "0" para números) em caso de falha, especificar um valor "padrão" (eu chamo de "outro") ou pedir nulo (onde T: classe). Também forneci modelos de exceção silenciosa e um modelo TryParse típico que retorna um bool indicando a ação executada e um parâmetro out mantém o novo valor. Portanto, nosso código pode fazer coisas assim

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>();

Eu não conseguia fazer com que os tipos Nullable entrassem na coisa toda de maneira muito limpa. Eu tentei por cerca de 20 minutos antes de jogar a toalha.


64
Pessoalmente, não sou fã de código que tenta / captura para determinar o resultado. A tentativa / captura deve ser usada para erros que ocorrem fora da lógica pretendida, IMO. hmmmmm
Pure.Krome

Se eu não quisesse que você usasse o código, não o teria postado! :)
TheSoftwareJedi 11/11/2008

Finalmente algo invisível. Eu gosto disso. :)
Arnis Lapsa

8
Você deve pelo menos alterar a cláusula "catch" para capturar apenas as exceções que ChangeType () gerará quando não puder "converter" a referência. Eu acho que você não gostaria que nenhum OutOfMemoryException, ExecutionEngineException, ThreadAbortException ou similar fosse tratado como um erro de conversão. Caso contrário, essas coisas serão bem difíceis de rastrear erros.
Christian

2
Acredito que ToOrNulltenha exatamente o mesmo comportamento que ToOrDefault(por exemplo, se você chamar ToOrDefaultum tipo de referência com uma conversão malsucedida, ela retornará null). Mas o mais importante, parece meio redundante para mim, pois var s = myObject as stringrealiza a mesma coisa que var s = myObject.ToOrNull<string>()- mas sem potencialmente ter que pegar um InvalidCastException. Estou esquecendo de algo?
Dan Tao

43

Eu tenho um método de extensão para registrar exceções:

public static void Log(this Exception obj)
{
  //your logging logic here
}

E é usado assim:

try
{
    //Your stuff here
}
catch(Exception ex)
{
    ex.Log();
}

[desculpe por postar duas vezes; o segundo é melhor projetado :-)]


2
Deve ler log estático público estático (esse obj de exceção) {} talvez?
28909 Chris S

Eu acho que isso é bom para exceções de BCL ou de terceiros, mas se você criar seus próprios tipos de exceção, poderá colocar o log na sua classe de exceção básica. Dessa forma, você não precisa se lembrar de chamar Log ().
si618

38
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);
    }
}

Útil para analisar uma string em um Enum.

public enum TestEnum
{
    Bar,
    Test
}

public class Test
{
    public void Test()
    {
        TestEnum foo = "Test".EnumParse<TestEnum>();
    }
 }

O crédito é para Scott Dorman

--- Editar para o projeto Codeplex ---

Perguntei a Scott Dorman se ele se importaria em publicar seu código no projeto Codeplex. Esta é a resposta que recebi dele:

Obrigado pelo aviso na publicação do SO e no projeto CodePlex. Votei sua resposta sobre a questão. Sim, o código está efetivamente em domínio público atualmente sob a CodeProject Open License ( http://www.codeproject.com/info/cpol10.aspx ).

Não tenho problemas com isso sendo incluído no projeto CodePlex e, se você quiser me adicionar ao projeto (o nome de usuário é sdorman), adicionarei esse método mais alguns métodos auxiliares de enumeração.


Este cenário de análise de enum surge o tempo todo ... tem que colocar isso na minha lib :-)
chakrit

Uau, eu tenho escrito métodos para mapear seqüências de caracteres para enumerações (comecei a usar o .NET). Obrigado, isso absolutamente ajudará!
226 Kevin Kevin

4
Você também pode nomear ToEnum <> (), pois ele vem após o objeto.
Neil

Note-se que Enum.TryParse <T> foi adicionado à Net 4.0 - blogs.msdn.com/bclteam
Dan Diplo

1
Eu não acho que esse método deve usar Trim. O corte da entrada deve ser de responsabilidade do chamador.
CodesInChaos

32

Acho este bastante útil:

public static class PaulaBean
{
    private static String paula = "Brillant";
    public static String GetPaula<T>(this T obj) {
        return paula;
    }
}

Você pode usá-lo no CodePlex.


2
Alguém pode ter a gentileza de explicar isso para os menos talentosos de nós?
jpbochi

hahaha Basta ler o artigo (comentário de Joel acima) - engraçado verdade, mas tendo estado praticamente no mesmo barco (no final da partida, não no final da Paula), é apenas engraçado olhando para trás! Uma vez um contratado foi contratado para trabalhar em um projeto no qual fui projetista / desenvolvedor líder - ela não estava sob meu controle direto, mas recebeu um trabalho da lista de trabalho de minhas equipes. Os chefes a elogiavam por ser brilhante (até contratá-la novamente mais tarde como líder de desenvolvimento!). Nunca ocorreu a eles que cada pedaço de código que ela escreveu ou projetou não havia chegado à produção e todos tinham que ser completamente reescritos do zero pela minha equipe!
Wolf5370

31

DateTimeExtensions

Exemplos:

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();

5
Eu sugiro renomear "SetTime" para "WithTime", pois na verdade não está definindo o valor existente. Bom caso contrário.
Jon Skeet

28
DateTime.Now.First () - primeiro o que? É apenas aparente no código de exemplo.
7118 mackenir

2
Muito agradável. Mas concorde que os nomes poderiam ser muito melhores.
bovium 7/11/08

DateTime.Now.First será suficientemente claro no Intellisense se o método estiver bem documentado.
22713 Ryan Lundy

29

gitorious.org/cadenza é uma biblioteca completa de alguns dos métodos de extensão mais úteis que eu já vi.


12 métodos de extensão bastante básicos. Estou um pouco desapontado com as rochas mono.
7118 mackenir

(Eu estou falando sobre a versão lançada, não o que você precisa para usar fonte de controle de chegar)
mackenir

28

Aqui está um que eu uso frequentemente para formatação de apresentações.

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());
}

Whoah, o tratamento de exceções de Pokemon ocultará problemas como ThreadAbortException, etc. Por favor, pegue algo específico.
JBRWilkinson

28

Aqui está uma lista de numeração romana. Não é usado com frequência, mas pode ser útil. Uso:

if ("IV".IsValidRomanNumeral())
{
   // Do useful stuff with the number 4.
}

Console.WriteLine("MMMDCCCLXXXVIII".ParseRomanNumeral());
Console.WriteLine(3888.ToRomanNumeralString());

A fonte:

    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();
        }
    }

Isso me lembra o Python PEP 313, que foi uma piada de April Fools para incluir literais de algarismos romanos em python: python.org/dev/peps/pep-0313
torial

25

Uma maneira conveniente de lidar com tamanhos:

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
        };
    }
}

Na minha opinião, esse é um estilo de codificação muito ruim. Em vez disso, devem ser usadas constantes, não lógica ofuscada.
Xxbbcc

24

Para controles 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));
}

Uso do 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
    }
}

Uso de 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();

Esqueci de mencionar, fique à vontade para usá-los no Codeplex ...


1
Como mencionado, isso é apenas para WinForms. Pode funcionar com o WPF, mas há problemas (descritos no comentário sobre o WPF em msdn.microsoft.com/en-us/library/… ). A melhor solução para o WPF que encontrei está descrita em geekswithblogs.net/lbugnion/archive/2009/09/05/… (embora seja uma propriedade estática, ela realmente não funciona como um método de extensão.)
scobi

23

O ThrowIfArgumentIsNull é uma boa maneira de fazer essa verificação nula que todos nós devemos fazer.

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");
    }
}

Abaixo está a maneira de usá-lo e funciona em todas as classes no seu espaço para nome ou onde quer que você use o espaço dentro.

internal class Test
{
    public Test(string input1)
    {
        input1.ThrowIfArgumentIsNull("input1");
    }
}

Não há problema em usar esse código no projeto CodePlex .


Eu também gosto disso, Jon tem o dele, e eu uso algo semelhante da Umbrella, que poderia deixar de lado a parte "ArgumentIs".
cfeduke

sim! este é um método de extensão kewl também :)
Pure.Krome

3
Se você usar o construtor ArgumentNullException com apenas 1 argumento de cadeia, esse argumento deverá ser apenas o nome do parâmetro e não a mensagem de erro. Portanto, seu código deve ficar assim: if (obj == null) lança novo ArgumentNullException (parameterName);
Tommy Carlier

Eu usaria default(T)isso e removeria o requisito de classe.
Joel Coehoorn

1
@ Joel: valores não padrão para tipos nativos são argumentos legítimos com mais frequência do que valores nulos. A verificação contra nulo faz mais sentido para mim do que a verificação contra o padrão. Claro, eu apenas generalizo toda a ideia dizendo Require.ThatArgument(input != null)ou Require.ThatArgument(personId > 0). Não é preciso muito mais código, é muito mais flexível e tem uma boa leitura. Tenho substituições adicionais que aceitam funcs para quando você deseja personalizar a mensagem de erro ou a própria exceção.
precisa

22

Sinto falta da declaração With do Visual Basic ao mudar para C #, então aqui vai:

public static void With<T>(this T obj, Action<T> act) { act(obj); }

E aqui está como usá-lo em C #:

someVeryVeryLonggggVariableName.With(x => {
    x.Int = 123;
    x.Str = "Hello";
    x.Str2 = " World!";
});

Economiza muita digitação!

Compare isso com:

someVeryVeryLonggggVariableName.Int = 123;
someVeryVeryLonggggVariableName.Str = "Hello";
someVeryVeryLonggggVariableName.Str2 = " World!";

colocar no projeto codeplex


4
Apenas um palpite, mas pense no que acontece se o seu T for uma estrutura.
Rauhotz 20/01/09

5
Também uso a sintaxe do inicializador de propriedades c # 3.0 sempre que possível para obter o mesmo resultado.
217 Steve Steve

3
@chakrit, aqui está um exemplo. Aplica-se apenas ao criar o objeto Botão n = novo Botão {Nome = "Botão1", Largura = 100, Altura = 20, Ativado = verdadeiro};
307 Steve

1
Isso seria útil quando você tem muitos eventos para conectar, porque a sintaxe do inicializador de propriedades do C # não suporta eventos.
Gabe

1
isso também é útil fora dos inicializadores de propriedades, porque você só pode usá-los ao criar um novo objeto. essa extensão pode funcionar em objetos criados anteriormente.
Brady Moritz

18

Pega um camelCaseWord ou PascalCaseWord e o "wordifica", ou seja, camelCaseWord => camel Case Word

public static string Wordify( this string camelCaseWord )
{
    // if the word is all upper, just return it
    if( !Regex.IsMatch( camelCaseWord, "[a-z]" ) )
        return camelCaseWord;

    return string.Join( " ", Regex.Split( camelCaseWord, @"(?<!^)(?=[A-Z])" ) );
}

Costumo usá-lo em conjunto com Capitalize

public static string Capitalize( this string word )
{
    return word[0].ToString( ).ToUpper( ) + word.Substring( 1 );
}

Exemplo de uso

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( );

Livre para usar no projeto codeplex


O agregado em maiúsculas é muito ruim para o desempenho, porque cria muitas instâncias de cadeia. Por que não usar word.Substring (1)?
Thomas Levesque

17

Eu achei este útil

public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> pSeq)
{
    return pSeq ?? Enumerable.Empty<T>();
}

Ele remove a verificação nula no código de chamada. Agora você poderia fazer

MyList.EmptyIfNull().Where(....)

Sim, se alguém esqueceu "Padrão de Objeto Nulo", esse método é útil para corrigi-lo. A coleção nunca deve ser nula.
Pavel Hodek

16

Converta um dobro em string formatado usando a cultura especificada:

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

Exemplo:

double test = 154.20;
string testString = test.ToCurrency("en-US"); // $154.20

13
Você deve usar decimal para a moeda mais você vai ter arredondamento problemas
Andrew Bullock

O que sobre o uso de um Enum no parâmetro em vez de corda lisa
Rulas

15

Abaixo está um método de extensão que adapta o código de Rick Strahl (e os comentários também) para impedir que você precise adivinhar ou ler a marca de ordem de bytes de uma matriz de bytes ou arquivo de texto cada vez que você o converte em uma string.

O snippet permite que você faça:

byte[] buffer = File.ReadAllBytes(@"C:\file.txt");
string content = buffer.GetString();

Se você encontrar algum erro, por favor, adicione aos comentários. Sinta-se à vontade para incluí-lo no projeto Codeplex.

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();
            }
        }
    }
}

Método muito útil, mas acho que não deveria ser e método de extensão.
Pop Catalin

Se você estiver escrevendo um editor de texto que provavelmente garante um método de extensão, mas concordo maior parte do tempo é provavelmente não mais do que um método particular estática
Chris S

15

Aqui está um que eu acabei de criar hoje.

// 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); }

Permite fazer isso:

var lname = thingy.NullOr(t => t.Name).NullOr(n => n.ToLower());

que é mais fluente e (IMO) mais fácil de ler do que isso:

var lname = (thingy != null ? thingy.Name : null) != null
    ? thingy.Name.ToLower() : null;

1
E se eu quiser thingy.NullOr(t => t.Count), onde Countestá um int? Você deve retornar default(TReturn)ao invés de null, dessa forma você não vai precisar da classrestrição e ele vai trabalhar para tipos de valor demasiado
Thomas Levesque

2
Deve ser necessário que TIn seja uma classe, caso contrário, esse método de extensão inteiro não faz sentido (os tipos de valor não podem ser nulos). E seu exemplo com t.Count funciona com o método de extensão acima. Você poderia dar uma segunda olhada?
Scobi

@ Scott: este é um método útil para um problema comum. No entanto, acredito que TReturn elseValue = default(TReturn)só está disponível para o .NET 4.0? Eu tenho o 3.5 SP1 e nunca vi essa construção (nem meu compilador). Acabei de mudar isso para dentro do método. Um problema, no entanto, é que o boxe de um tipo anulável para objetar para uso com o método gera um resultado inesperado (0 vs nulo esperado).
Jim Schubert

@ Jim: a default(T)palavra-chave existe desde o VS2005, mas acho que os parâmetros padrão são um novo recurso do .NET 4. A maneira mais fácil de contornar isso deve ser ter duas variantes, uma que aceita o parâmetro e outra que não. Vou atualizar a resposta para ser compatível com CLR 2.0. Quanto ao boxe - esse é o ponto default. Serão dados inicializados com 0 para um tipo de valor e nulos para todos os tipos de referência. Um retorno de um tipo de valor deve permanecer unboxed por toda a função.
scobi

@ Scott: Minha pergunta era sobre o parâmetro padrão, que eu só vi em linguagens dinâmicas como Ruby. Meu argumento sobre tipos anuláveis ​​é que o retorno x.Valuedeve retornar nulo (se, por exemplo, int?for nulo) ou o valor se int?tiver um valor. Retornar 0quando int? x = nullé passado e encaixotado ao objeto é um caso estranho. Eu já vi verificações semelhantes para tipos anuláveis ​​em bibliotecas como nhibernate fluente e linfu (acho) para este caso específico, permitindo que você elimine a restrição de classe conforme sugerido anteriormente.
Jim Schubert

14

"Por favor, marque suas respostas com uma aceitação para colocar o código no projeto Codeplex."

Por quê? Todas as coisas neste site sob CC-by-sa-2.5 . Portanto, basta colocar seu Projeto de extensão de extensão sob a mesma licença e você pode usá-lo livremente.

De qualquer forma, aqui está uma função String.Reverse, com base nesta pergunta .

/// <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);
}

String já não implementa IEnumerable <char>? Então você só precisa retornar new String (input.Reverse ());
Iain Galloway

Uma implementação usando StringBuilder deve ser mais rápida.
CodesInChaos

1
@CodeInChaos O Benchmarking no stackoverflow.com/questions/228038 mediu que o StringBuilder é mais lento.
Michael Stum

Você está certo. Parece que os requisitos de segurança do encadeamento (provavelmente para garantir a imutabilidade da string retornada pelo ToString) atrasam bastante o StringBuilder.
CodesInChaos

2
Espero que você não encontre substitutos ou personagens que combinem.
dalle

14

Eu cansei da verificação nula tediosa ao extrair valores do MySqlDataReader, então:

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

Obviamente, isso pode ser usado com qualquer SqlDataReader.


Hangy e Joe fizeram alguns bons comentários sobre como fazer isso, e desde então tive a oportunidade de implementar algo semelhante em um contexto diferente, então aqui está outra versão:

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

2
Isso também deve funcionar como um método de extensão para o IDataReader.
228 hangy

2
Na verdade, faça o parâmetro "this" do tipo IDataRecord para obter compatibilidade máxima. Na minha versão disso, tenho uma sobrecarga que requer um ordinal, que a versão fieldName chama. Salva o "GetOrdinal" seguido de uma pesquisa por nome.
Joel Mueller

Existe uma implementação adequada, que pode lidar com qualquer tipo de valor: rabdullin.com/journal/2008/12/6/…
Rinat Abdullin

Graças Rinat, eu realmente tenho esse baixo a um único método genérico - ver stackoverflow.com/questions/303287
Adam Lassek

Todos esses métodos parecem desnecessários, pois você pode usar a aspalavra-chave para obter um valor de um leitor que permita nulo. Se você combinar o ??operador coalescente nulo com o operador as, poderá até ter um valor padrão não nulo para ir diretamente para um tipo de valor. Veja stackoverflow.com/questions/746767/…
stevehipwell

14

Irritou-me o fato de o LINQ me fornecer um OrderBy que pega uma classe implementando IComparer como argumento, mas não suporta a passagem de uma simples função comparadora anônima. Eu retifiquei isso.

Esta classe cria um IComparer a partir da sua função comparadora ...

/// <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
}

... e esses métodos de extensão expõem minhas novas sobrecargas OrderBy em enumerables. Duvido que isso funcione para o LINQ to SQL, mas é ótimo para o 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);
    }
}

Você pode colocar isso no codeplex, se quiser.


13

Este é para o MVC, ele adiciona a capacidade de gerar um <label />tag para a Htmlvariável que está disponível em todos ViewPage. Espero que seja útil para outras pessoas que tentam desenvolver extensões semelhantes.

Usar:

<%= Html.Label("LabelId", "ForId", "Text")%>

Resultado:

<label id="LabelId" for="ForId">Text</label>

Código:

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

Confira MvcContrib.FluentHtml
Arnis Lapsa

Provavelmente, isso deve ser duplicado com o Literal.
Mark Hurd

12

Vire isto:

DbCommand command = connection.CreateCommand();
command.CommandText = "SELECT @param";

DbParameter param = command.CreateParameter();
param.ParameterName = "@param";
param.Value = "Hello World";

command.Parameters.Add(param);

... nisso:

DbCommand command = connection.CreateCommand("SELECT {0}", "Hello World");

... usando este método de extensão:

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;
      }
   }
}

Mais métodos de extensão do ADO.NET: DbExtensions

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.