5

在我们的应用程序中,我们有一些来自翻译的字符串可以包含变量。例如在Can i have a {beverage}?{beverage}部分应替换为一个变量。我当前的实现通过拥有所有变量的名称和值的字典,并替换正确的字符串来工作。但是我想通过引用注册变量,这样如果值改变了,结果字符串也会改变。通常使用关键字传递参数ref就可以了,但我不确定如何将它们存储在字典中。

翻译解析器:

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

主文件

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

首先你注册了 like a 的替代品,{beverage}"cola"运行时想把它改成另一个: "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;
        });
}
于 2012-04-27T12:00:16.720 回答