.純益:ある文字列です。書式形式を挿入するために値をオブジェクトの財産込ん。

StackOverflow https://stackoverflow.com/questions/357447

  •  21-08-2019
  •  | 
  •  

質問

私の答えは"No"がほしいと思って人には本物のライブラリこのためにはできるか---ウッド...)

私が何を意味するのかを示してい例です。ることもあったの

class Person {
  string Name {get; set;}
  int NumberOfCats {get; set;}
  DateTime TimeTheyWillDie {get; set;}
}

すればよいのでしょうかないようになります:

static void Main() {
  var p1 = new Person() {Name="John", NumberOfCats=0, TimeTheyWillDie=DateTime.Today};
  var p2 = new Person() {Name="Mary", NumberOfCats=50, TimeTheyWIllDie=DateTime.Max};

  var str = String.Format(

"{0:Name} has {0:NumberOfCats} cats and {1:Name} has {1:NumberOfCats} cats.  They will die {0:TimeTheyWillDie} and {1:TimeTheyWillDie} respectively
", p1, p2);

  Console.WriteLine(str);
}

なんだろうけど、日本人の場合ュー形式で行うようなことやれば書には、図書室していきますか?かべきではないものでその調子でがんばってくださいいと思いないことを再実装します。

役に立ちましたか?

解決

編集:あなたは、各オブジェクトにIFormattableを実装する必要はありません...それはPITA、厳しく制限し、かつかなり大きなメンテナンス負担になるだろう。ただ、リフレクションとICustomFormatterとするIFormatProviderを使用して、それは、のいずれかののオブジェクトで動作します。 String.Formatのは、パラメータとして1を取るために過負荷を持っています。

私はこの前に考えたことはありませんが、あなたは私に興味をそそら - ので、私はそれを素早く旋回を与えなければなりませんでした。私はプロパティ値に渡される追加の書式文字列を許可することを選んだ、と(あなたが簡単にそれを追加することもできますが)、それは唯一の非インデックス化し、アクセス可能な特性で動作することがあります。

public class ReflectionFormatProvider : IFormatProvider, ICustomFormatter {
    public object GetFormat(Type formatType) {
        return formatType == typeof(ICustomFormatter) ? this : null;
    }

    public string Format(string format, object arg, IFormatProvider formatProvider) {
        string[] formats = (format ?? string.Empty).Split(new char[] { ':' }, 2);
        string propertyName = formats[0].TrimEnd('}');
        string suffix = formats[0].Substring(propertyName.Length);
        string propertyFormat = formats.Length > 1 ? formats[1] : null;

        PropertyInfo pi = arg.GetType().GetProperty(propertyName);
        if (pi == null || pi.GetGetMethod() == null) {
            // Pass thru
            return (arg is IFormattable) ? 
                ((IFormattable)arg).ToString(format, formatProvider) 
                : arg.ToString();
        }

        object value = pi.GetGetMethod().Invoke(arg, null);
        return (propertyFormat == null) ? 
            (value ?? string.Empty).ToString() + suffix
            : string.Format("{0:" + propertyFormat + "}", value);
    }
}

そして、あなたのわずかに変更された例:

var p1 = new Person() {Name="John", NumberOfCats=0, TimeTheyWillDie=DateTime.Today};
var p2 = new Person() {Name="Mary", NumberOfCats=50, TimeTheyWillDie=DateTime.MaxValue};

var str = string.Format(
    new ReflectionFormatProvider(),
    @"{0:Name} has {0:NumberOfCats} cats and {1:Name} has {1:NumberOfCats} cats. 
    They will die {0:TimeTheyWillDie:MM/dd/yyyy} and {1:TimeTheyWillDie} respectively.
    This is a currency: {2:c2}.", 
    p1, 
    p2,
    8.50M
);

Console.WriteLine(str);

を出力します:

John has 0 cats and Mary has 50 cats. 
They will die 12/10/2008 and 12/31/9999 11:59:59 PM respectively.
This is a currency: $8.50.

他のヒント

あなたは、あなたのクラスのtoString()をオーバーライドすることができます。

良い記事ここ

の後に何が「:」あなたのクラスのToStringメソッドに引数として渡され
。 単なる文字列を受け入れるToStringメソッド、および「名前」を宣言し、「NumberOfCats」などはそのパラメータに渡されます。

EDIT:あなたはSystem.IFormattableを実装する必要があります。これは動作します:

class Person : IFormattable
{
    public override string ToString()
    {
        return "Person";
    }

    public string ToString(string format, IFormatProvider formatProvider)
    {
        if (format == "Name")
        {
            return "John";
        }
        if (format == "NumberOfCats")
        {
            return "12";
        }
        return "Unknown format string";
    }

}

class Program
{
    static void Main(string[] args)
    {
        Person p = new Person();
        Console.WriteLine(string.Format("Name = {0:Name}",p));
        Console.WriteLine(string.Format("NumberOfCats = {0:NumberOfCats}", p));
    }
}

マイライブラリ "膨張" をチェックしてください。

ここNugetオン: http://nuget.org/List/Packages/Expansiveする

ここでGitHubの場合: http://github.com/anderly/expansiveする

私は実際にどのようにこれが表示されません

"{0:Name} has {0:NumberOfCats} cats and {1:Name} has {1:NumberOfCats} cats.  They will die {0:TimeTheyWillDie} and {1:TimeTheyWillDie} respectively", p1, p2);

これよりも優れてます:

"{0} has {1} cats and {2} has {3} cats.  They will die {4} and {5} respectively
", p1.Name, p1.NumberOfCats, p2.Name, p2.NumberOfCats, p1.TimeTheyWillDie, p2.TimeTheyWillDie);
あなたが最初のものでインテリセンスヘルプを失っているので、

実際には、だけでなく、それは失敗しやすいですが、おそらくIDEでの書き込みに時間がかかるだろう。

そして、あなたはこのような何かをしたい場合、あなたは常にそれのために拡張メソッドをかき立てることができます。私はそれはカントー、悪夢のようになります賭けます。

ブーまたはNemerleはこのような何かを持っています。ノー簡単な答えで、ここ数年のカップルのためにそれを行うための良いシンプルな方法を考えることを試みた。

あなたができる最善のは、あなたがするIFormatProviderを所有して提供し、手動で入力(安っぽい部分...)を解析している。

これは多くのPythonの世界を"someString%locals()." いを示唆するものは、カップルでの基本的な休憩から文字列になります。形式の作品

  • 通常のプレースホルダの表記は、文字列のフォーマット情報コロンの後には、い物件です。

  • のプレースホルダー指数({0,{1など)は参照numberes引数のparam args、それをご希望の機能を描画するために全体の文字列の各パラメータが渡されます。ることを連結され?返される文字列として配列?

だがこの一部だ、その場合、スキップすることができ指数表記の全て(そう{NumberOfCats}の代わりに{0:NumberOfCats}も用物件の名前の後に形式のプロバイダ{NumberOfCats:c}.消費のメタデータから入力オブジェクトなも苦労しました。

scroll top