2013-07-12 14 views
6

mam:String.Format metodę rozszerzenia

public static string Format(this string text, params object[] args) 
{ 
    return string.Format(text, args); 
} 

Więc mogę zrobić:

"blablabla {0}".Format(variable1); 

Czy to dobry/zły? Czy może stać się jeszcze krótszy? Chcę mieć ciągi budować bezproblemowo, jak pisanie tekstu bez obawy przed lub po parametrów i rzeczy:

// bad 
return "date: " + DateTime.Now.ToString("dd.MM.yyyy") + "\ntime: " + DateTime.Now.ToString("mm:HH:ss") + "\nuser: " + _user + " (" + _status + ")"; 

// better, but you have to deal with order of {0}...{n} and order of parameters 
return string.Format("date: {0}\ntime: {1}\user: {2} ({3})", ...); 

// ideal 
return "date: {DateTime.Now{dd:MM:yyyy}}\ntime: {...}\nuser: {_user} ({_status})"; 
+0

Uważam, że oczekiwany wynik tego pomysłu jest bardzo mylący. – Steve

+0

"Czy to jest dobre/złe?": Pytasz o opinie, które nie są tutaj tematem [SO]. – Richard

+0

@Richard, to tylko jedno z kilku pytań, które zadałem = P – Sinatr

Odpowiedz

3

Cóż, jeden złe rzeczą jest, że mając tylko jedną metodę params object[] wymusić dodatkowy przydzielanie tablicy dla połączenia.

Możesz zauważyć, że string.Format ma zakres przeciążeń do przyjmowania małej liczby argumentów (są one bardzo często używane) - Sugerowałbym ich powielenie.

swój „idealny” scenariusz może być wykonywane poprzez ponowne pisanie metodą string.Format, ale trzeba by przejść w wartościach, tj

return "date: {date}\ntime: {...}\nuser: {_user} ({_status})" 
    .Format(new { date = DateTime.Now, _user, _status }); 

(i stosując własną metodę zwyczaj Format lub one like this) - ale pamiętaj, że wymusza to nowe wystąpienie obiektu na każde połączenie.

W pewnym momencie kompilator mono miał flagę eksperymentalną, aby włączyć to bezpośrednio. Nie wiem, czy to się utrzymuje.

+0

Fajny pomysł na umieszczenie w ciągach moich identyfikatorów, a następnie zastąpienie ich wartościami, których potrzebuję. Dzięki! – Sinatr

1

To zależy, czy kodujesz sam, czy masz zespół. W zespole jest to bardzo zły pomysł, ponieważ wszyscy będą musieli nauczyć się tej metody.

Innym problemem jest Format z argumentami dotyczącymi łańcuchów, które przypadkowo zawierają nawiasy o nieprawidłowym indeksie, takim jak {1} zamiast {2}. W ten sposób tylko zły ciąg spowoduje awarię całej aplikacji. Użyłem czegoś podobnego do mojego logowania i musiałem użyć try-catch dla FormatExceptions.

+0

Jeśli wstawię metodę wypróbowania/catch wewnątrz metody rozszerzenia i podpiszę w jakiś inny sposób, aby sygnalizować błędy programowania (na przykład, dodając na końcu łańcucha, coś takiego jak "omg, parametr {10} brakuje"), metoda rozszerzenia jest duża zaleta (więc nie muszę duplikować try/catch dla każdego formatu). Każdy zespół ma swoje własne "stylizacje" lub wspólne rozwiązania dla typowych przypadków. Gdybyś był zdezorientowany przez składnię - szybko zobaczysz, co to jest bezpośrednio w Visual Studio. Więc nie widzę tutaj dużego problemu. – Sinatr

2

Używam również podobnej metody przedłużania i podoba mi się, podaję też informacje o kulturze w metodzie rozszerzenia, która jest dla systemu ustawiona w moim przypadku.

public static string Format(this string formatTemplate, params object[] args) 
{ 
    return string.Format(SysSettings.CultureInfo, formatTemplate, args); 
} 

Usages:

return "date: {0:dd.MM.yyyy}\ntime: {1:mm:HH:ss}\nuser: {2} ({3})".Format(DateTime.Now, DateTime.Now, _user, _status); 
+0

Niesamowity pomysł z kulturą, dzięki. Zostałem popchnięty, by używać neutralnej kultury dla kropki dziesiętnej, gdy używam 'double' lub' float' i nigdy, gdy używam 'int', a dzięki metodzie rozszerzenia mogę zabić wszystko w 1 sesji! – Sinatr

+0

Spowoduje to błąd kompilacji, jeśli spróbujesz przekazać 2 argumenty, z których pierwszy będzie ciągiem. '" {0} - {1} ". Format (" przykład ", 1);' ponieważ będzie pasował do statycznego podpisu String.Format zamiast rozszerzenia – GP89

3

To nie całkiem pasuje do Twojego ideału, ale coś takiego może pracować dla Ciebie:

public static class Extensions 
{ 
    public static string Format(this object data, string format) 
    { 
     var values = new List<object>(); 
     var type = data.GetType(); 
     format = Regex.Replace(format, @"(^|[^{])\{([^{}]+)\}([^}]|$)", x => 
     { 
      var keyValues = Regex.Split(x.Groups[2].Value, 
             "^([^:]+):?(.*)$") 
            .Where(y => !string.IsNullOrEmpty(y)); 

      var key = keyValues.ElementAt(0); 
      var valueFormat = keyValues.Count() > 1 ? 
           ":" + keyValues.ElementAt(1) : 
           string.Empty; 


      var value = GetValue(key, data, type); 

      values.Add(value); 
      return string.Format("{0}{{{1}{2}}}{3}", 
            x.Groups[1].Value, 
            values.Count - 1, 
            valueFormat, 
            x.Groups[3].Value); 
     }); 


     return string.Format(format, values.ToArray()); 
    } 

    private static object GetValue(string name, object data, Type type) 
    { 
     var info = type.GetProperty(name); 
     return info.GetValue(data, new object[0]); 
    } 
} 

ten powinien pozwolić, aby zrobić ten rodzaj formatowanie na dowolny obiekt:

new {Person = "Me", Location = "On holiday"} 
    .Format("{Person} is currently {Location}"); 

Umożliwia również dodanie formatowania:

new {Person = "Me", Until = new DateTime(2013,8,1)} 
    .Format("{Person} is away until {Until:yyyy-MM-dd}); 

Co to jest dla Ciebie? Jestem pewien, że kod mógłby zostać poprawiony pod względem wydajności, ale działa!

+0

Twoim pomysłem jest wygenerowanie tablicy argumentów * przed * wywoływanie Format i wstawić * nazwę * zmiennej do ciągu formatu zamiast '{0}', co jest fajne. Dzięki. – Sinatr

+0

Tak, z wyjątkiem metody rozszerzenia formatu jest wywoływana na obiekcie, a nie tablicy. W moich przykładach jest to instancja typu anonimowego, ale tak naprawdę może to być dowolny obiekt, taki jak obiekt domeny: (np: var person = new Person ("Aaron", "Janes"); person.Format ("{ LastName}, {FirstName} ");) –

+0

Obecnie metoda rozszerzenia, którą wybrałem, nie obsługuje indeksowanych właściwości, więc: nowy {Items = new [] {" One "," Two "}} .Format (" Pierwszy element: { Przedmioty [0]} "); nie będzie działać. Jednak dodanie podpory dla indeksatorów powinno być względnie banalne. –

Powiązane problemy