按引用的字典值
本文关键字:字典 引用 | 更新日期: 2023-09-27 18:32:23
在我们的应用程序中,我们有一些来自翻译的字符串,可以包含变量。例如,在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;
});
}
}
主.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
关键字一样。
另一种使用包装器的方法。每次重新注册变量时,都可以包装变量。
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
}
在提供的代码中,我看到
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?"
首先,您像"cola"
一样注册{beverage}
的替代品,但之后想在运行时将其更改为另一个:"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;
});
}