In our application we have some strings coming from translation that can contain variables. For example in Can i have a {beverage}?
the {beverage}
part should be replaced with a variable.
My current implementation works by having a Dictionary of the name and value of all variables, and just replacing the correct string. However i'd like to register the variables by reference, so that if the value is ever changed the resulting string is changed as well. Usually passing a parameter with the ref
keyword would do the trick, but i'm unsure on how to store those in a Dictionary.
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}?"));
Is this possible at all, or am i just approaching the problem incorrectly? I fear that the only solution would involve unsafe code (pointers).
So in short, i'd like to store a variable in a Dictionary, change the original variable and get the changed value from the Dictionary. Like you would do with the ref
keyword.
Another way to use wrappers. You can wrap your variables every time when you regiester them.
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;
});
}
}
Edit:
But actually, I think it's impossible without unsafe code to track variables in a way that you want to do. Value-types and references to reference-type stored in stack, and if you just replace reference, it will not affect to real object in heap (reference to that object you store in the dictionary). So that you need to have references (say pointers) to stack memory.
Edit again: I was wrong!
It is possible to track any varaible using expressions:
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With