.صافي:هل هناك سلسلة.شكل نموذج لإدخال قيمة كائن الملكية في سلسلة ؟

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

  •  21-08-2019
  •  | 
  •  

سؤال

أعتقد أن الإجابة المباشرة على السؤال هو " لا " ولكن أنا على أمل أن شخصا ما قد كتب بسيط المكتبة للقيام بذلك (أو أستطيع أن أفعل ذلك...آه...)

اسمحوا لي أن تظهر ما أنا أبحث عن مثال على ذلك.لنفترض أن لدي التالية:

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

لا أحد يعرف إذا كان هناك تنسيق من أجل القيام بشيء من هذا القبيل أو إذا كان شخص ما قد كتب مكتبة نفعل ذلك ؟ وأنا أعلم أنه لا ينبغي أن يكون من الصعب جدا, ولكن أنا أفضل أن لا يكون reimplementing عجلة القيادة.

هل كانت مفيدة؟

المحلول

وتحرير: ليس لديك لتنفيذ IFormattable لكل كائن ... التي تريد ان تكون بيتا، مما يحد بشدة، وعبء صيانة كبيرة إلى حد ما. مجرد استخدام التأمل وIFormatProvider مع ICustomFormatter وانه سوف يعمل مع أي الكائن. String.Format ديه الزائد لتأخذ واحدة كمعلمة.

ولقد فكرت أبدا من هذا من قبل، ولكن كنت مفتون لي - لذلك اضطررت لاعطائها دوامة سريعة. لاحظ أن اخترت للسماح لسلسلة تنسيق إضافية لتمريرها إلى قيمة العقار، وأنه يعمل فقط مع خصائص غير مفهرسة ويمكن الوصول إليها (على الرغم من أنك يمكن بسهولة إضافة ذلك).

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" سيتم تمريرها في تلك المعلمة.

وتحرير: يجب تنفيذ 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

في جيثب هنا: 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، وتحليل المدخلات يدويا (الجزء كربي ...).

إذا كنت ترغب في تحليل شكل سلسلة نفسك, عليك أن تنظر في هذا...:

على Spring.NET المشروع Spring.NET التعبير اللغة في الربيع.الأساسية.فإنه يتيح لك الاستعلام كائن الرسم البياني بالإشارة إلى خصائص باستخدام السلاسل.استخدام الخاص بك سبيل المثال ، يمكن أن يتصور شيئا من هذا القبيل:

var person = new Person { Name = "joe", Email = new Email { Address = "joe@joe.com" } };

var message = string.Format("{0}'s e-mail is {1}",
    ExpressionEvaluator.GetValue(person, "Name"), 
    ExpressionEvaluator.GetValue(person, "Email.Address"));

(أنا ربما لن متجر إلكتروني مثل هذا, ولكن أنا لا يمكن أن يأتي مع أي شيء أفضل)

هذا شيء أن تفعل الكثير في بيثون العالم باستخدام "someString % من السكان المحليين()." ماذا كنت تقترح على الرغم من لديه بضع الأساسية فواصل من السلسلة.تنسيق الأعمال:

  • عادة نائبا التدوين لديه سلسلة تنسيق المعلومات بعد القولون ، في حين كنت تريد أن تفعل الوصول إلى الملكية.

  • العنصر النائب المؤشرات ({0, {1, الخ) عادة ما يشير إلى numberes الحجج في params وسائط, ولكن يبدو كنت ترغب في وظيفة الخاص بك لجعل السلسلة بأكملها لكل المعلمة التي يتم تمريرها في.يجب أن تكون متصلا?عاد كسلسلة المصفوفة ؟

إذا كنت قد ينتهي كتابة هذا بنفسك, في هذه الحالة يمكنك تخطي مؤشر التدوين تماما (حتى {NumberOfCats} بدلا من {0:NumberOfCats} أو حتى استخدام اسم الخاصية تليها الشكل مزود {NumberOfCats:c}.استهلاك البيانات الوصفية من إدخال كائن لا يجب أن تكون صعبة جدا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top