.순:거기에는 문자열을 사용합니다.형식으로 형태를 삽입하기 위한 값을 객체의 속성으로 문자열?
-
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}. 메타 데이터 소비. 입력 객체에서 너무 힘들지 않아야합니다.