.순:거기에는 문자열을 사용합니다.형식으로 형태를 삽입하기 위한 값을 객체의 속성으로 문자열?

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

사람이 알고 있는 경우에도 형식으로 무언가를 하기를 위해 다음과 같이나 누군가가 있다면 작성된 라이브러리 할 수 있나요?나는 그것이 어렵진 않지만,나는 오히려되지 않을 다시 구현합니다.

도움이 되었습니까?

해결책

편집 : 각 객체에 대해 ifortable을 구현할 필요는 없습니다. 그것은 피타, 심각하게 제한적이며 상당히 큰 유지 보수 부담 일 것입니다. 반사와 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

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에 글을 쓰는 데 더 오래 걸릴 것입니다.

그리고 이와 같은 일을하고 싶다면 항상 확장 방법을 채찍질 할 수 있습니다. 나는 그것이 악몽처럼 보일 것이라고 확신한다.

Boo 또는 Nemerle에는 이와 같은 것이 있습니다. 나는 쉬운 대답없이 몇 년 동안 그것을 할 수있는 멋진 간단한 방법을 생각하려고 노력했습니다.

당신이 할 수있는 최선은 자신의 iformatprovider를 제공하고 입력을 수동으로 구문 분석하는 것입니다 (Crappy Part ...).

로 결정한 경우를 분석해서 형식 문자열 자신을,당신은 이 점을 고려해야 합니다...:

이 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 % LOCALS ()"를 사용하여 파이썬 세계에서하는 일입니다. 당신이 제안하는 것은 String.format의 작동 방식에서 몇 가지 근본적인 휴식을 가지고 있습니다.

  • 일반적으로 자리 표시 자 표기법에는 콜론 다음에 문자열 서식 정보가 있지만 속성 액세스를 원합니다.

  • 자리 표시 자 지수 ({0, {1 등)는 일반적으로 Params Args의 번호 인수를 참조하지만, 기능이 전달 된 각 매개 변수의 전체 문자열을 렌더링하는 것으로 보입니다. 동의해야합니까? 문자열 배열로 반환 되었습니까?

따라서이 사실을 직접 작성하게 될 수 있습니다.이 경우 색인 표기법을 완전히 건너 뛸 수 있습니다 ({0 : 숫자 로프 카트} 대신 {numberofcats} 또는 속성 이름을 사용한 다음 형식 제공자 {numberofcats : c}. 메타 데이터 소비. 입력 객체에서 너무 힘들지 않아야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top