2010-03-09 3 views
1

는 현재 내가이 일을하고있다 :텍스트가 모든 개체 속성에서 변환됩니다. 더 좋은 방법이 있습니까?

나는처럼 보이는 텍스트가 :

Hello ${user.name}, this is .... 

을 그리고 나는이 수행 어쩌면 루프에 어떻게 든 반사를 사용하여

public string TransformUser(User user, string text) 
{ 
    StringBuilder sb = new StringBuilder(text); 

    sb.Replace("${user.name}", user.Name); 

    ... 
    ... 

    return sb.ToString(); 
} 

는, 더 나은 방법이됩니다 공공 재산 클래스를 통해?

편집

는이 방법 일반을 할 수 있을까, 그래서 그것을 어떤 개체를 전달할 수 있습니까?

답변

1

반사를 사용하여 다음과 같이 대략 보일 것이다 문자열의 키를 대체하는 모든 속성을 통해 반복 :

var args = new object[0]; 
foreach(var prop in typeof(User).GetProperties()) { 
    if (prop.CanRead) { 
    string val = prop.GetGetMethod().Invoke(user, args).ToString(); 
    sb.Replace("${user." + prop.Name +"}", val); 
    } 
} 

그것은 속성이 게터를 가지고 있는지 확인하는 CanRead를 사용하고 값을 읽을 수있는 게터를 호출합니다. 값은 단순히 ToString을 사용하여 문자열로 변환되며 이는 기본 동작 유형 (필요한 동작에 따라 다름)에서 작동합니다. 대소 문자를 구분하므로 사용자가 소문자로 키를 작성하는 경우 ToLower을 사용할 수 있습니다 (예에서와 같이).

+3

또한 사용할 수 있습니다 여기에


코드의 ...

,이 클래스는, 약간의 조정이 필요합니다 당신의 정확한 요구에 맞게하지만 너무 열심히하지 않아야 prop.GetGetMethod() 대신 prop.GetValue (user, null) 호출 (...) –

+0

어떤 객체를 사용하는 메소드로 이것을 래핑하는 것이 가능합니까? – Blankman

+1

@Fadrian : 고마워, 그거 좋은 제안이야! @Blankman : 예, 모든 객체에서 작동 할 수 있습니다. 일반 메소드에 포장하고'typeof (T)'를 사용하거나 (객체 유형이 컴파일 타임에 알려짐)'user.GetType()'을 사용하여'object' 유형의 인자의 현재 유형을 실행 시간. –

0

typeof(User).GetProperties()을 호출하여 속성을 반복 할 수 있습니다.

1

StringTemplate 클래스는 사용자의 필요에 맞게 수정 될 수 있습니다. 이는 String.Format처럼 동작합니다. 큰 차이가 있습니다. 인덱스가 아닌 자리 표시 자의 이름을 사용할 수 있습니다. 형식을 지정할 값은 IDictionary<string, object> 또는 임의의 개체로 지정할 수 있습니다.이 경우 각 개체 틀은 같은 이름의 속성 값으로 대체됩니다. 예를 들어

: 동일한 템플릿을 여러 번 사용해야하는 경우

// with a dictionary : 
var values = new Dictionary<string, object> 
{ 
    { "Title", "Mr." }, 
    { "LastName", "Smith" } 
}; 
string a = StringTemplate.Format("Hello {Title} {LastName}", values); 

// with an anonymous type : 
string b = StringTemplate.Format(
    "Hello {Title} {LastName}", 
    new { Title = "Mr.", LastName = "Smith" }); 

, 당신은 StringTemplate의 인스턴스를 생성하고 성능 향상을 위해 재사용 할 수 있습니다 (템플릿 문자열은 한 번만 구문 분석 할 것입니다).

String.Format과 같은 형식 수정자를 지정할 수도 있습니다.

public class StringTemplate 
{ 
    private string _template; 
    private static Regex _regex = new Regex(@"(?<open>{+)(?<key>\w+)(?<format>:[^}]+)?(?<close>}+)", RegexOptions.Compiled); 

    public StringTemplate(string template) 
    { 
     template.CheckArgumentNull("template"); 
     this._template = template; 
     ParseTemplate(); 
    } 

    private string _templateWithIndexes; 
    private List<string> _placeholders; 

    private void ParseTemplate() 
    { 
     _placeholders = new List<string>(); 
     MatchEvaluator evaluator = (m) => 
     { 
      if (m.Success) 
      { 
       string open = m.Groups["open"].Value; 
       string close = m.Groups["close"].Value; 
       string key = m.Groups["key"].Value; 
       string format = m.Groups["format"].Value; 

       if (open.Length % 2 == 0) 
        return m.Value; 

       open = RemoveLastChar(open); 
       close = RemoveLastChar(close); 

       if (!_placeholders.Contains(key)) 
       { 
        _placeholders.Add(key); 
       } 

       int index = _placeholders.IndexOf(key); 
       return string.Format("{0}{{{1}{2}}}{3}", open, index, format, close); 
      } 
      return m.Value; 
     }; 
     _templateWithIndexes = _regex.Replace(_template, evaluator); 
    } 

    private string RemoveLastChar(string str) 
    { 
     if (str.Length > 1) 
      return str.Substring(0, str.Length - 1); 
     else 
      return string.Empty; 
    } 

    public static implicit operator StringTemplate(string s) 
    { 
     return new StringTemplate(s); 
    } 

    public override string ToString() 
    { 
     return _template; 
    } 

    public string Format(IDictionary<string, object> values) 
    { 
     values.CheckArgumentNull("values"); 

     object[] array = new object[_placeholders.Count]; 
     for(int i = 0; i < _placeholders.Count; i++) 
     { 
      string key = _placeholders[i]; 
      object value; 
      if (!values.TryGetValue(key, out value)) 
      { 
       value = string.Format("{{{0}}}", key); 
      } 
      array[i] = value; 
     } 
     return string.Format(_templateWithIndexes, array); 
    } 

    private IDictionary<string, object> MakeDictionary(object obj) 
    { 
     Dictionary<string, object> dict = new Dictionary<string, object>(); 
     Type type = obj.GetType(); 
     foreach (string propName in _placeholders) 
     { 
      var prop = type.GetProperty(propName); 
      if (prop != null) 
       dict.Add(propName, prop.GetValue(obj, null)); 
     } 
     return dict; 
    } 

    public string Format(object values) 
    { 
     return Format(MakeDictionary(values)); 
    } 

    public static string Format(string template, IDictionary<string, object> values) 
    { 
     return new StringTemplate(template).Format(values); 
    } 

    public static string Format(string template, object values) 
    { 
     return new StringTemplate(template).Format(values); 
    } 
} 
관련 문제