5

私たちのアプリケーションでは、変数を含むことができる翻訳からの文字列がいくつかあります。たとえば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キーワードで行うように。

4

2 に答える 2

2

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

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

編集:

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

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

式を使用して任意の変数を追跡できます。

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
}
于 2012-04-27T12:19:06.840 に答える
0

提供されたコードで私が見る

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?"

最初{beverage}にlike aの代用を登録しますが、後で実行時に別のもの"cola"に変更したい: . Thieは私に考えさせます:保存されたものに対して「勝つ」オプションのパラメーターを受け入れる関数だけを使用しないのはなぜですか?"fanta"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;
        });
}
于 2012-04-27T12:00:16.720 に答える