webentwicklung-frage-antwort-db.com.de

Angeben von benutzerdefinierten Zeichenfolgenplatzhaltern für das Zeichenfolgenformat

Ich habe eine Schnur 

string str ="Enter {0} patient name";

Ich verwende string.format, um es zu formatieren.

String.Format(str, "Hello");

Wenn ich möchte, dass der Patient auch aus einer Konfig abgerufen wird, muss ich str in etwas wie "Enter {0} {1} name" ändern. Es wird also {1} durch einen zweiten Wert ersetzt. Das Problem ist, dass ich anstelle von {1} ein anderes Format wie {pat} verwenden möchte. Aber wenn ich versuche zu benutzen, wirft es einen Fehler. Der Grund, warum ich ein anderes Format haben möchte, ist, dass es viele Dateien gibt, die ich so ändern muss (die {0}, {1} usw. enthalten können). Ich brauche also einen benutzerdefinierten Platzhalter, der zur Laufzeit ausgetauscht werden kann.

26
Punit Singhi

Vielleicht möchten Sie FormatWith 2.0 von James Newton-King überprüfen. Sie können Eigenschaftsnamen als Formatierungs-Token wie diese verwenden:

var user = new User()
{
    Name = "Olle Wobbla",
    Age = 25
};

Console.WriteLine("Your name is {Name} and your age is {Age}".FormatWith(user));

Sie können es auch mit anonymen Typen verwenden.

UPDATE: Es gibt auch eine ähnliche Lösung by Scott Hanselman , die jedoch als eine Reihe von Erweiterungsmethoden auf Object anstelle von String implementiert ist.

UPDATE 2012 : Sie können das NETFx String.FormatWith-Erweiterungsverfahren von Calrius Consulting NuGet-Paket unter NuGet.org herunterladen.

UPDATE 2014 : Es gibt auch StringFormat.NET und das StringFormat von littlebit

50
Magnus Lindhe

Regex mit einer MatchEvaluator scheint eine gute Option zu sein:

static readonly Regex re = new Regex(@"\{([^\}]+)\}", RegexOptions.Compiled);
static void Main()
{
    string input = "this {foo} is now {bar}.";
    StringDictionary fields = new StringDictionary();
    fields.Add("foo", "code");
    fields.Add("bar", "working");

    string output = re.Replace(input, delegate (Match match) {
        return fields[match.Groups[1].Value];
    });
    Console.WriteLine(output); // "this code is now working."
}
17
Marc Gravell
object[] myInts = new int[] {8,9}; 

Sie können jedoch mit:

object[] myInts = new string[] { "8", "9" }; 
string bar = string.Format("{0} {1}", myInts); 
3
mujtaba Hyder

Ich sah alle Antworten oben, konnte die Frage nicht richtig verstehen :) 

Gibt es einen bestimmten Grund, warum der folgende Code Ihre Anforderung nicht erfüllt?

string myFirstStr = GetMyFirstStrFromSomewhere();
string mySecondStr = GetMySecondStrFromSomewhere();

string result = "Enter " + myFirstStr + " " + mySecondStr + " name";
3
Chansik Im

Hier ist eine weitere Version davon, die ich hier gefunden habe: http://www.reddit.com/r/programming/comments/bodml/beef_up_params_in_c_5_to_solve_lambda_abuse/c0nrsf1

Jede Lösung hierfür wird Reflexion beinhalten, was weniger als ideal ist, aber hier ist sein Code mit einigen anderen wichtigen Leistungsproblemen behoben. (Keine Fehlerprüfung. Fügen Sie es hinzu, wenn Sie möchten.):

1) Verwendet direkte Laufzeitreflexion, kein DataBinder-Overhead

2) Verwendet keine regulären Ausdrücke, verwendet eine Analyse und einen Zustand mit einem Durchgang.

3) Konvertiert die Zeichenfolge nicht in eine Zwischenzeichenfolge und konvertiert sie dann erneut in das endgültige Format.

4) Ordnet und verkettet sie mit einem einzigen StringBuilder, statt Zeichenfolgen überall neu zu erstellen und sie zu neuen Zeichenfolgen zu verketten.

5) Entfernt den Stapelaufwand für das Aufrufen eines Delegaten für n Ersetzungsoperationen.

6) Im Allgemeinen ist ein einzelner Durchlauf, der relativ linear skaliert wird (immer noch einige Kosten für jede Requisiten-Suche und verschachtelte Requisiten-Suche, aber das ist das.)

public static string FormatWith(this string format, object source)
{
    StringBuilder sbResult = new StringBuilder(format.Length);
    StringBuilder sbCurrentTerm = new StringBuilder();
    char[] formatChars = format.ToCharArray();
    bool inTerm = false;
    object currentPropValue = source;

    for (int i = 0; i < format.Length; i++)
    {
        if (formatChars[i] == '{')
            inTerm = true;
        else if (formatChars[i] == '}')
        {
            PropertyInfo pi = currentPropValue.GetType().GetProperty(sbCurrentTerm.ToString());
            sbResult.Append((string)(pi.PropertyType.GetMethod("ToString", new Type[]{}).Invoke(pi.GetValue(currentPropValue, null), null)));
            sbCurrentTerm.Clear();
            inTerm = false;
            currentPropValue = source;
        }
        else if (inTerm)
        {
            if (formatChars[i] == '.')
            {
                PropertyInfo pi = currentPropValue.GetType().GetProperty(sbCurrentTerm.ToString());
                currentPropValue = pi.GetValue(source, null);
                sbCurrentTerm.Clear();
            }
            else
                sbCurrentTerm.Append(formatChars[i]);
        }
        else
            sbResult.Append(formatChars[i]);
    }
    return sbResult.ToString();
} 
2
Bryan Legend

Sie können auch das Beispiel von Marc Gravell und das Klassenobjekt Extend the String verwenden:

public static class StringExtension
{
    static readonly Regex re = new Regex(@"\{([^\}]+)\}", RegexOptions.Compiled);
    public static string FormatPlaceholder(this string str, Dictionary<string, string> fields)
    {
        if (fields == null)
            return str;

        return re.Replace(str, delegate(Match match)
        {
            return fields[match.Groups[1].Value];
        });

    }
}

Verwendungsbeispiel:

String str = "I bought a {color} car";
Dictionary<string, string> fields = new Dictionary<string, string>();
fields.Add("color", "blue");

str.FormatPlaceholder(fields));
1
Ole K

Es ist wahrscheinlich besser, Ersetzen für das benutzerdefinierte Feld und Format für den Rest zu verwenden, z.

string str = "Enter {0} {pat} name";
String.Format(str.Replace("{pat}", "Patient"), "Hello");
0
Dean Povey

Ich wollte etwas, das mehr wie Pythons String-Formatierung funktioniert, also schrieb ich Folgendes: https://Gist.github.com/samwyse/b225b32ae1aea6fb27ad9c966b9ca90b

Verwenden Sie es so:

Dim template = New FormatFromDictionary("{cat} vs {dog}")
Dim d = New Dictionary(Of String, Object) From {
    {"cat", "Felix"}, {"dog", "Rex"}}
Console.WriteLine(template.Replace(d)) ' Felix vs Rex
0
samwyse