Есть ли аналог VB.Net метода Strings.Format в C#?

84
18 февраля 2022, 00:20

Имеется старый код на VB.Net, который портируется на C#. В процессе возникла проблема с портированием Strings.Format.
В коде используются
именованные форматы даты времени,
именованные числовые форматы и
определяемые пользователем строковые форматы
(так и не понял, почему на странице документации по Strings.Format не доступна вся информация об именованных форматах).

Проблема заключается в том, что вышеуказанные форматы сохраняются в двоичных конфигурационных файлах для которых необходимо обеспечить обратную совместимость. К примеру, имеется такой VB метод:

Public Function StringConvert(ByVal sValue As String, ByVal sFormatString As String) As String
    Dim RetWert As String
    Dim neuWert As String = Trim(sValue)
    Dim format As String = Trim(sFormatString)
    If format = "String" Then
        RetWert = neuWert
    ElseIf format = "General Date" Or
      format = "Long Date" Or
      format = "Short Date" Or
      format = "Medium Date" Or
      format = "Long Time" Or
      format = "Medium Time" Or
      format = "Short Time" Then
        If IsDate(sValue) Then
            RetWert = Format(CDate(neuWert), format)
        Else
            RetWert = ""
        End If
    ElseIf format = "General Number" Or
      format = "Currency" Or
      format = "Fixed" Or
      format = "Standard" Or
      format = "Percent" Or
      format = "Scientific" Then
        If IsNumeric(sValue) Then
            RetWert = Format(CDbl(neuWert), format)
        Else
            RetWert = ""
        End If
    ElseIf format = "Yes/No" Or
      format = "True/False" Or
      format = "On/Off" Then
        If IsNumeric(sValue) Then
            RetWert = Format(CBool(neuWert), format)
        Else
            RetWert = ""
        End If
    Else
        If InStr(format, "@") > 0 Or
           InStr(format, "&") > 0 Or
           InStr(format, "<") > 0 Or
           InStr(format, ">") > 0 Or
           InStr(format, "!") > 0 Then
            RetWert = Format(neuWert, format)
        ElseIf InStr(format, "c") > 0 Or InStr(format, "y") > 0 Or
               InStr(format, "d") > 0 Or InStr(format, "h") > 0 Or
               InStr(format, "w") > 0 Or InStr(format, "s") > 0 Or
               InStr(format, "m") > 0 Or InStr(format, "t") > 0 Or
               InStr(format, "q") > 0 Or InStr(format, "+") > 0 Then
            If IsNumeric(sValue) Then
                RetWert = Format(CDate(neuWert), format)
            Else
                RetWert = ""
            End If
        ElseIf InStr(format, " ") > 0 Or InStr(format, "%") > 0 Or
               InStr(format, "0") > 0 Or InStr(format, "-") > 0 Or
               InStr(format, "#") > 0 Or InStr(format, "E") > 0 Or
               InStr(format, ".") > 0 Or InStr(format, "e") > 0 Or
               InStr(format, ",") > 0 Or InStr(format, "+") > 0 Then
            If IsNumeric(sValue) Then
                RetWert = Format(CDbl(neuWert), format)
            Else
                RetWert = ""
            End If
        Else
            RetWert = CStr(neuWert)
        End If
    End If
    StringConvert = RetWert
End Function

Пробовал создать свой IFormatProvider для форматирования DateTime, но он просто преобразует символы строковых форматов дат (в примере ниже это h и t). Конечно можно импортировать пространство имён Microsoft.VisualBasic и использовать метод далее, но (насколько я понимаю) этот подход не будет работать с .Net Core, что критично.

Имеется ли аналог Strins.Format в C#? Может быть есть какая-либо библиотека (.Net Standard)? Каким образом, по Вашему мнению, можно оптимально решить эту задачу?

"Поиграться" можно здесь.

public class VBDateTimeFormatProvider : IFormatProvider, ICustomFormatter
{
    public object GetFormat(Type formatType)
    {
        return formatType == typeof(ICustomFormatter)
            ? this : null;
    }
    private readonly Dictionary<string, string> _map = new Dictionary<string, string>()
    {
        {"General Date", "G"},
        {"Long Date", "D"},
        {"Short Date", "d"},
        {"Medium Date", "D"},
        {"Long Time", "T"},
        {"Medium Time", "T"},
        {"Short Time", "t"}
    };
    public string Format(string format, object arg, IFormatProvider formatProvider)
    {
        format = format.Trim();
        return _map.ContainsKey(format)
            ? DateTime.Parse(arg.ToString()).ToString(_map[format], CultureInfo.CurrentCulture)
            : string.Empty;
    }
}
// var dt = new DateTime(2020, 1, 1).ToString();
// Console.WriteLine(DateTime.Parse(dt).ToString(format, new VBDateTimeFormatProvider()));
// выводит: "S12orA DaAe"
Answer 1

VB.NET использует тот же .NET, что и C#. Так что берёшь проект на C#, идешь в references и добавляешь библиотеку Microsoft.VisualBasic. После чего используешь сколько хочешь.

Кстати, по твоей же ссылке написано:

Применяется к

.NET Core 3.1, 3.0

.NET Framework 4.8, 4.7.2, 4.7.1, 4.7, 4.6.2, 4.6.1, 4.6, 4.5.2, 4.5.1, 4.5, 4.0, 3.5, 3.0, 2.0, 1.1

READ ALSO
Организация вывода в массиве

Организация вывода в массиве

Нужно вывести произведение чисел <50, не используя условие if для проверки значения pr в выводе :

92
Vue js - как программно отрендерить компонент?

Vue js - как программно отрендерить компонент?

Есть компонент, который принимает один параметр для отображенияВозникла необходимость отрендерить его не в шаблоне, а в методе (для последующей...

634
Не могу понять, как написать манипулятор для оператора ввода

Не могу понять, как написать манипулятор для оператора ввода

Есть класс, который отвечает за установку двунаправленного соединения между процессами(через pipe), ввод в stdin дочернего процесса и вывод через...

102
Как нарисовать линию с символьным паттерном?

Как нарисовать линию с символьным паттерном?

Необходимо нарисовать линию со сложным паттерном в виде символа при помощи QPainterКак в примере ниже

69