2012-04-27 7 views
3

私たちのアプリケーションでは、変数を含むことができる変換からいくつかの文字列があります。たとえば、Can i have a {beverage}?の場合、{beverage}の部分を変数に置き換える必要があります。 私の現在の実装は、すべての変数の名前と値のディクショナリを持ち、正しい文字列を置き換えるだけで動作します。しかし、値を変更すると結果の文字列も変更されるように、変数を参照として登録したいと思います。通常、refキーワードのパラメータを渡すと、そのトリックが実行されますが、辞書に格納する方法はわかりません。参照によるディクショナリ値

TranslationParser:

static class TranslationParser 
{ 
    private const string regex = "{([a-z]+)}"; 
    private static Dictionary<string, object> variables = new Dictionary<string,object>(); 

    public static void RegisterVariable(string name, object value) 
    { 
     if (variables.ContainsKey(name)) 
      variables[name] = value; 
     else 
      variables.Add(name, value); 
    } 

    public static string ParseText(string text) 
    { 
     return Regex.Replace(text, regex, match => 
     { 
      string varName = match.Groups[1].Value; 

      if (variables.ContainsKey(varName)) 
       return variables[varName].ToString(); 
      else 
       return match.Value; 
     }); 
    } 
} 

main.cs

 string bev = "cola"; 
     TranslationParser.RegisterVariable("beverage", bev); 
     //Expected: "Can i have a cola?" 
     Console.WriteLine(TranslationParser.ParseText("Can i have a {beverage}?")); 
     bev = "fanta"; 
     //Expected: "Can i have a fanta?" 
     Console.WriteLine(TranslationParser.ParseText("Can i have a {beverage}?")); 

は全くこのことは可能ですか、私はちょうど間違って問題に近づいていますか?私は唯一の解決策が安全でないコード(ポインタ)を含むことに懸念します。

要するに、私は辞書に変数を保存し、元の変数を変更して、変更された値を辞書から取得したいと思います。 refキーワードと同じように。コードで

+0

http://en.wikipedia.org/wiki/Rope_(computer_science)が対象となり得ます。 –

+0

@DaveBishあなたは速い読者です!しかし、その記事は記憶ではないようですが、それは問題ではありません。文字列はxmlファイルから来て、バイナリには含まれません。 – TJHeuvel

+0

そして、文字列の操作はうまくいっているようですが、私はちょうど辞書に基本的に参照を格納したいと思います。 – TJHeuvel

答えて

1

ラッパーを使用する別の方法。変数を登録するたびに変数をラップすることができます。

class ObjectWrapper 
{ 
    private object _value; 

    public ObjectWrapper(object value) 
    { 
     _value = value; 
    } 

    public override string ToString() 
    { 
     return _value.ToString(); 
    } 
} 

static class TranslationParser 
{ 
    private const string regex = "{([a-z]+)}"; 
    private static Dictionary<string, ObjectWrapper> variables = new Dictionary<string, ObjectWrapper>(); 

    public static void RegisterVariable(string name, object value) 
    { 
     var wrapped = new ObjectWrapper(value); 
     if (variables.ContainsKey(name)) 
      variables[name] = wrapped; 
     else 
      variables.Add(name, wrapped); 
    } 

    public static string ParseText(string text) 
    { 
     return Regex.Replace(text, regex, match => 
     { 
      string varName = match.Groups[1].Value; 

      if (variables.ContainsKey(varName)) 
       return variables[varName].ToString(); 
      else 
       return match.Value; 
     }); 
    } 
} 

編集:

しかし、実際に、私はそれはあなたがやりたいように、変数を追跡するために、安全でないコードなしには不可能だと思います。値の型とスタックに格納された参照型への参照。参照を置き換えるだけでは、ヒープ内の実オブジェクト(辞書に格納したオブジェクトへの参照)には影響しません。したがって、メモリをスタックするための参照(ポインタなど)が必要です。

もう一度編集:私は間違っていた!

式を使用して任意のvaraibleを追跡することが可能である:

class Wrapper 
{ 
    private readonly Dictionary<string, MemberExpression> _registrations = 
     new Dictionary<string, MemberExpression>(); 

    public void Register<T>(string name, Expression<Func<T>> expr) 
    { 
     _registrations[name] = (MemberExpression)expr.Body; 
    } 

    public object GetValue(string name) 
    { 
     var expr = _registrations[name]; 
     var fieldInfo = (FieldInfo)expr.Member; 
     var obj = ((ConstantExpression)expr.Expression).Value; 
     return fieldInfo.GetValue(obj); 
    } 
} 
private static void Main(string[] args) 
{ 
    var wrapper = new Wrapper(); 
    int x = 0; 
    storage.Register("x",() => x); 
    Console.WriteLine(wrapper.GetValue("x")); //0 
    x = 1; 
    Console.WriteLine(wrapper.GetValue("x")); //1 
} 
+0

はい、それはrich.okellyも示唆されています。テストされ、働いている(upvoted同様に;))。しかし、そのむしろ賑やかですが、その唯一の方法があれば。 – TJHeuvel

+0

私はなぜ違いがあるのだろうと思っていました。カスタムクラスは参照型で、System.Stringは値型なのですか? – TJHeuvel

+0

きれいな答えをありがとう:) – TJHeuvel

0

私はあなたが最初"cola"のように{飲料}のsubstitudeをregitserが、別のものにそれを実行でを変更したいの後ということ

string bev = "cola"; 
TranslationParser.RegisterVariable("beverage", bev); 
//Expected: "Can i have a cola?" 
Console.WriteLine(TranslationParser.ParseText("Can i have a {beverage}?")); 
bev = "fanta"; 
//Expected: "Can i have a fanta?" 

を参照してください提供:"fanta"。 Thieは私に思考を導きます:保存されたものに対して "勝利"するオプションのパラメータを受け入れるParseText関数だけではなぜですか?このよう

public static string ParseText(string text, string preferedValue=null) 
{ 
     return Regex.Replace(text, regex, match => 
     { 
      string varName = match.Groups[1].Value; 

      if (variables.ContainsKey(varName)) 
      { 
       if(!string.IsNullOrEmpty(preferedValue)) //IF THERE ISPREFERED VALUE               
         return preferedValue;    //RETURN THAT ONE 

       return variables[varName].ToString(); 
      } 
      else 
       return match.Value; 
     }); 
} 
+0

これは、通常のString.Formatと同じ種類のものです。 1つの場所ですべての変数を知りたいのですが、アプリケーションのすべてのクラスが新しい変数を登録でき、他のすべてのクラスが翻訳を取得する可能性があります。 – TJHeuvel

+0

提案してくれてありがとう:) – TJHeuvel

+0

@TJHeuvel:確かに、投稿を見てみると、柔軟性がさらに増したと思うので、Translatorのコンシューマーのデフォルトの翻訳された値がOKでない場合は、彼にもっと妥当ですか?これは正しいのではないですか? – Tigran